https://github.com/sjinks/node-modsecurity
ModSecurity Connector for Node.js
https://github.com/sjinks/node-modsecurity
modsec modsecurity security waf
Last synced: 10 months ago
JSON representation
ModSecurity Connector for Node.js
- Host: GitHub
- URL: https://github.com/sjinks/node-modsecurity
- Owner: sjinks
- License: mit
- Created: 2023-05-27T14:09:41.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2025-03-01T09:16:09.000Z (12 months ago)
- Last Synced: 2025-03-05T05:02:22.413Z (11 months ago)
- Topics: modsec, modsecurity, security, waf
- Language: JavaScript
- Homepage:
- Size: 283 KB
- Stars: 4
- Watchers: 3
- Forks: 1
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# node-modsecurity
[](https://github.com/sjinks/node-modsecurity/actions/workflows/ci.yml)
[](https://sonarcloud.io/summary/new_code?id=sjinks_node-modsecurity)
[](https://github.com/sjinks/node-modsecurity/actions/workflows/dependency-review.yml)
A [ModSecurity](https://github.com/SpiderLabs/ModSecurity#readme) connector for Node.js
## Prerequisites
Because this library provides Node.js bindings to `libmodsecurity`, `libmodsecurity` along with its development files has to be installed.
See: https://pkgs.org/search/?q=libmodsecurity
### Ubuntu
```sh
sudo apt-get install -y libmodsecurity3 libmodsecurity-dev
```
### CentOS
```sh
sudo yum -y install epel-release
sudo yum -y install libmodsecurity libmodsecurity-devel
```
### MacOS
TBD
### Windows
[Not supported](https://github.com/SpiderLabs/ModSecurity#windows)
### Caveats
Old versions of libmodsecurity are sometimes buggy: for example, libmodsecurity up to 3.0.8 (since at least 3.0.6) may [crash](https://github.com/SpiderLabs/ModSecurity/issues/2872)
if you forget to call to `Transaction::processConnection()` or `Transaction::processURI()`; libmodsecurity 3.0.6 leaks memory.
Theerefore, it is recommended to install (or, more likely, build) the latest version of libmodsecurity yourself. The [official documentation](https://github.com/SpiderLabs/ModSecurity#compilation)
and [project Wiki](https://github.com/SpiderLabs/ModSecurity/wiki/Compilation-recipes-for-v3.x) provide instructions on how to compile the library.
As of the time of writing, libmodsecurity 3.0.9 seems to be OK: my tests did not find memory leaks nor was I able to crash it from Node.js.
## Installation
```sh
npm install modsecurity
```
## Usage
TBD; please see [this](https://github.com/sjinks/node-modsecurity/blob/245049f87b276fd56c1493b37afa437d04613e72/test/integration/lifecycle.mjs#L39-L85) for usage example.
tl;dr:
```js
import { createServer } from 'node:http';
import { ModSecurity, Rules, Transaction } from 'modsecurity';
const modsec = new ModSecurity();
// Optional: set logging callback:
modsec.setLogCallback((message) => console.log(message));
const rules = new Rules();
rules.loadFromFile('rules.conf');
const server = createServer((request, response) => {
const tx = new Transaction(modsec, rules);
let res;
res = tx.processConnection(request.socket.remoteAddr, request.socket.remotePort, request.socket.localAddress, request.socket.localPort);
if (typeof res === 'object') {
return processIntervention(res, response, tx);
}
if (false === res) {
// modsecurity returned an error
}
res = tx.processURI(request.url, request.method, request.httpVersion);
if (typeof res === 'object') {
return processIntervention(res, response, tx);
}
let key = null;
for (const v of request.rawHeaders) {
if (key === null) {
key = v;
} else {
tx.addRequestHeader(key, v);
key = null;
}
}
res = tx.processRequestHeaders();
if (typeof res === 'object') {
return processIntervention(res, response, tx);
}
if (Buffer.isBuffer(request.body)) {
res = tx.appendRequestBody(request.body);
if (typeof res === 'object') {
return processIntervention(res, response, tx);
}
}
res = tx.processRequestBody();
if (typeof res === 'object') {
return processIntervention(res, response, tx);
}
// Handle request here
tx.processLogging();
});
function processIntervention(intervention, response, tx) {
response.statusCode = intervention.status;
if (intervention.url) {
response.setHeader('Location', intervention.url);
}
// intervention.log contains additional information
response.end();
tx.processLogging();
}
server.listen(3000);
```