Skip to content

Commit 6c4b812

Browse files
committed
Merge branch 'main' of github.com:AikidoSec/node-RASP into hansott-patch-1
* 'main' of github.com:AikidoSec/node-RASP: (34 commits) When Zen starts Add note about loading env variables in ESM mode Add separate heartbeat e2e test Fix e2e test Add e2e test Fix missing outbound hostname Add extra comment to make intent clear Reduce diff Format code after merge Update package.json Update .github/workflows/lint-code.yml Update .prettierignore Remove prettier config in adonis sample app Fix duplicate prettier install & format Add end2end tests for blocking outbound connections Fix test Fix tests Align message with expected test message Simplify InspectionResult and move domains to normal config Update ipAddress type for attack wave ...
2 parents 5559d8b + a9c6324 commit 6c4b812

File tree

101 files changed

+1813
-821
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

101 files changed

+1813
-821
lines changed

.github/CODE_OF_CONDUCT.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,23 @@ diverse, inclusive, and healthy community.
1717
Examples of behavior that contributes to a positive environment for our
1818
community include:
1919

20-
* Demonstrating empathy and kindness toward other people
21-
* Being respectful of differing opinions, viewpoints, and experiences
22-
* Giving and gracefully accepting constructive feedback
23-
* Accepting responsibility and apologizing to those affected by our mistakes,
20+
- Demonstrating empathy and kindness toward other people
21+
- Being respectful of differing opinions, viewpoints, and experiences
22+
- Giving and gracefully accepting constructive feedback
23+
- Accepting responsibility and apologizing to those affected by our mistakes,
2424
and learning from the experience
25-
* Focusing on what is best not just for us as individuals, but for the overall
25+
- Focusing on what is best not just for us as individuals, but for the overall
2626
community
2727

2828
Examples of unacceptable behavior include:
2929

30-
* The use of sexualized language or imagery, and sexual attention or advances of
30+
- The use of sexualized language or imagery, and sexual attention or advances of
3131
any kind
32-
* Trolling, insulting or derogatory comments, and personal or political attacks
33-
* Public or private harassment
34-
* Publishing others' private information, such as a physical or email address,
32+
- Trolling, insulting or derogatory comments, and personal or political attacks
33+
- Public or private harassment
34+
- Publishing others' private information, such as a physical or email address,
3535
without their explicit permission
36-
* Other conduct which could reasonably be considered inappropriate in a
36+
- Other conduct which could reasonably be considered inappropriate in a
3737
professional setting
3838

3939
## Enforcement Responsibilities

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ A clear and concise description of what went wrong.
1111

1212
**To Reproduce**
1313
Steps to reproduce the behavior:
14+
1415
1.
1516
2.
1617
3.
@@ -22,6 +23,7 @@ What you expected to happen.
2223
What actually happened (include logs or error messages if possible).
2324

2425
**Environment**
26+
2527
- OS: [e.g. Ubuntu 22.04, macOS 15.0, Windows 11]
2628
- Language version: [e.g. 18, 20, 22]
2729
- Framework: [e.g. Express, Hono, Fastify]

.github/workflows/lint-code.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ jobs:
3333
run: npm i -g [email protected]
3434
- run: npm run install-lib-only
3535
- run: npm run build
36-
- run: npm run lint
36+
- name: Run Linter for JavaScript/TypeScript
37+
run: npm run lint
38+
- name: Check formatting
39+
run: npm run format:check
3740
- name: Check Rust formatting
3841
run: cd instrumentation-wasm && cargo fmt --check
3942
- name: Run Rust Linter

.prettierignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.tap/
2+
internals/
3+
wasm/
4+
.next/
5+
out/
6+
build/
7+
dist/
8+
coverage/
9+
.esm-tests/

.prettierrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
"useTabs": false,
55
"semi": true,
66
"singleQuote": false
7-
}
7+
}

README.md

Lines changed: 72 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
# Zen, in-app firewall for Node.js | by Aikido
44

5-
[![NPM Version](https://img.shields.io/npm/v/%40aikidosec%2Ffirewall?style=flat-square)](https://www.npmjs.com/package/@aikidosec/firewall)
6-
[![Codecov](https://img.shields.io/codecov/c/github/AikidoSec/firewall-node?style=flat-square&token=AJK9LU35GY)](https://app.codecov.io/gh/aikidosec/firewall-node)
7-
[![NPM License](https://img.shields.io/npm/l/%40aikidosec%2Ffirewall?style=flat-square)](https://github.com/AikidoSec/firewall-node/blob/main/LICENSE)
8-
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
9-
[![Unit tests](https://github.com/AikidoSec/firewall-node/actions/workflows/unit-test.yml/badge.svg)](https://github.com/AikidoSec/firewall-node/actions/workflows/unit-test.yml)
10-
[![End to end tests](https://github.com/AikidoSec/firewall-node/actions/workflows/end-to-end-tests.yml/badge.svg)](https://github.com/AikidoSec/firewall-node/actions/workflows/end-to-end-tests.yml)
5+
[![NPM Version](https://img.shields.io/npm/v/%40aikidosec%2Ffirewall?style=flat-square)](https://www.npmjs.com/package/@aikidosec/firewall)
6+
[![Codecov](https://img.shields.io/codecov/c/github/AikidoSec/firewall-node?style=flat-square&token=AJK9LU35GY)](https://app.codecov.io/gh/aikidosec/firewall-node)
7+
[![NPM License](https://img.shields.io/npm/l/%40aikidosec%2Ffirewall?style=flat-square)](https://github.com/AikidoSec/firewall-node/blob/main/LICENSE)
8+
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
9+
[![Unit tests](https://github.com/AikidoSec/firewall-node/actions/workflows/unit-test.yml/badge.svg)](https://github.com/AikidoSec/firewall-node/actions/workflows/unit-test.yml)
10+
[![End to end tests](https://github.com/AikidoSec/firewall-node/actions/workflows/end-to-end-tests.yml/badge.svg)](https://github.com/AikidoSec/firewall-node/actions/workflows/end-to-end-tests.yml)
1111

1212
Zen, your in-app firewall for peace of mind– at runtime.
1313

@@ -19,100 +19,100 @@ It protects your Node.js apps by scanning user input and where that data eventua
1919

2020
Zen will autonomously protect your Node.js applications against:
2121

22-
* 🛡️ [NoSQL injection attacks](https://www.aikido.dev/blog/web-application-security-vulnerabilities)
23-
* 🛡️ [SQL injection attacks](https://www.aikido.dev/blog/the-state-of-sql-injections)
24-
* 🛡️ [Command injection attacks](https://www.aikido.dev/blog/command-injection-in-2024-unpacked)
25-
* 🛡️ [Prototype pollution](./docs/prototype-pollution.md)
26-
* 🛡️ [Path traversal attacks](https://owasp.org/www-community/attacks/Path_Traversal)
27-
* 🛡️ [Server-side request forgery (SSRF)](./docs/ssrf.md)
28-
* 🛡️ [Attack wave detection](https://help.aikido.dev/zen-firewall/zen-features/attack-wave-protection)
29-
* 🛡️ JS injection
22+
- 🛡️ [NoSQL injection attacks](https://www.aikido.dev/blog/web-application-security-vulnerabilities)
23+
- 🛡️ [SQL injection attacks](https://www.aikido.dev/blog/the-state-of-sql-injections)
24+
- 🛡️ [Command injection attacks](https://www.aikido.dev/blog/command-injection-in-2024-unpacked)
25+
- 🛡️ [Prototype pollution](./docs/prototype-pollution.md)
26+
- 🛡️ [Path traversal attacks](https://owasp.org/www-community/attacks/Path_Traversal)
27+
- 🛡️ [Server-side request forgery (SSRF)](./docs/ssrf.md)
28+
- 🛡️ [Attack wave detection](https://help.aikido.dev/zen-firewall/zen-features/attack-wave-protection)
29+
- 🛡️ JS injection
3030

3131
Zen operates autonomously on the same server as your Node.js app to:
3232

33-
* ✅ Secure your app like a classic web application firewall (WAF), but with none of the infrastructure or cost.
34-
* ✅ Auto-generate API specifications
35-
* ✅ Block known threat actors and bots.
36-
* ✅ Geo-fencing to block or allow a selection of countries
37-
* ✅ Rate limit specific API endpoints by IP or by user
38-
* ✅ Allows you to block specific users manually
33+
- ✅ Secure your app like a classic web application firewall (WAF), but with none of the infrastructure or cost.
34+
- ✅ Auto-generate API specifications
35+
- ✅ Block known threat actors and bots.
36+
- ✅ Geo-fencing to block or allow a selection of countries
37+
- ✅ Rate limit specific API endpoints by IP or by user
38+
- ✅ Allows you to block specific users manually
3939

4040
## Supported libraries and frameworks
4141

4242
Zen for Node.js 16+ is compatible with:
4343

4444
### Web frameworks
4545

46-
*[Express](docs/express.md) 4.x, 5.x
47-
*[Hono](docs/hono.md) 4.x
48-
*[hapi](docs/hapi.md) 21.x
49-
*[micro](docs/micro.md) 10.x
50-
*[Next.js](docs/next.md) 12.x, 13.x and 14.x
51-
*[Fastify](docs/fastify.md) 4.x and 5.x
52-
*[Koa](docs/koa.md) 3.x and 2.x
53-
*[NestJS](docs/nestjs.md) 10.x and 11.x
54-
*[Restify](docs/restify.md) 11.x, 10.x, 9.x and 8.x
46+
-[Express](docs/express.md) 4.x, 5.x
47+
-[Hono](docs/hono.md) 4.x
48+
-[hapi](docs/hapi.md) 21.x
49+
-[micro](docs/micro.md) 10.x
50+
-[Next.js](docs/next.md) 12.x, 13.x and 14.x
51+
-[Fastify](docs/fastify.md) 4.x and 5.x
52+
-[Koa](docs/koa.md) 3.x and 2.x
53+
-[NestJS](docs/nestjs.md) 10.x and 11.x
54+
-[Restify](docs/restify.md) 11.x, 10.x, 9.x and 8.x
5555

5656
### Database drivers
5757

58-
*[`mongodb`](https://www.npmjs.com/package/mongodb) 4.x, 5.x and 6.x _(npm package versions, not MongoDB server versions)_
59-
*[`mongoose`](https://www.npmjs.com/package/mongoose) 8.x, 7.x and 6.x
60-
*[`pg`](https://www.npmjs.com/package/pg) 8.x and 7.x
61-
*[`mysql`](https://www.npmjs.com/package/mysql) 2.x
62-
*[`mysql2`](https://www.npmjs.com/package/mysql2) 3.x
63-
*[`mariadb`](https://www.npmjs.com/package/mariadb) 3.x
64-
*[`sqlite3`](https://www.npmjs.com/package/sqlite3) 5.x
65-
*[`node:sqlite`](https://nodejs.org/api/sqlite.html)
66-
*[`better-sqlite3`](https://www.npmjs.com/package/better-sqlite3) 12.x, 11.x, 10.x, 9.x and 8.x
67-
*[`postgres`](https://www.npmjs.com/package/postgres) 3.x
68-
*[`@clickhouse/client`](https://www.npmjs.com/package/@clickhouse/client) 1.x
69-
*[`@prisma/client`](https://www.npmjs.com/package/@prisma/client) 5.x
58+
-[`mongodb`](https://www.npmjs.com/package/mongodb) 4.x, 5.x and 6.x _(npm package versions, not MongoDB server versions)_
59+
-[`mongoose`](https://www.npmjs.com/package/mongoose) 8.x, 7.x and 6.x
60+
-[`pg`](https://www.npmjs.com/package/pg) 8.x and 7.x
61+
-[`mysql`](https://www.npmjs.com/package/mysql) 2.x
62+
-[`mysql2`](https://www.npmjs.com/package/mysql2) 3.x
63+
-[`mariadb`](https://www.npmjs.com/package/mariadb) 3.x
64+
-[`sqlite3`](https://www.npmjs.com/package/sqlite3) 5.x
65+
-[`node:sqlite`](https://nodejs.org/api/sqlite.html)
66+
-[`better-sqlite3`](https://www.npmjs.com/package/better-sqlite3) 12.x, 11.x, 10.x, 9.x and 8.x
67+
-[`postgres`](https://www.npmjs.com/package/postgres) 3.x
68+
-[`@clickhouse/client`](https://www.npmjs.com/package/@clickhouse/client) 1.x
69+
-[`@prisma/client`](https://www.npmjs.com/package/@prisma/client) 5.x
7070

7171
### Cloud providers
7272

73-
*[`@google-cloud/functions-framework`](https://www.npmjs.com/package/@google-cloud/functions-framework) 4.x, 3.x
74-
*[`@google-cloud/pubsub`](https://www.npmjs.com/package/@google-cloud/pubsub) 5.x, 4.x
75-
* ✅ Google Cloud Functions
76-
* ✅ AWS Lambda
73+
-[`@google-cloud/functions-framework`](https://www.npmjs.com/package/@google-cloud/functions-framework) 4.x, 3.x
74+
-[`@google-cloud/pubsub`](https://www.npmjs.com/package/@google-cloud/pubsub) 5.x, 4.x
75+
- ✅ Google Cloud Functions
76+
- ✅ AWS Lambda
7777

7878
### ORMs and query builders
7979

8080
See list above for supported database drivers.
8181

82-
*[`sequelize`](https://www.npmjs.com/package/sequelize)
83-
*[`knex`](https://www.npmjs.com/package/knex)
84-
*[`typeorm`](https://www.npmjs.com/package/typeorm)
85-
*[`bookshelf`](https://www.npmjs.com/package/bookshelf)
86-
*[`drizzle-orm`](https://www.npmjs.com/package/drizzle-orm)
82+
-[`sequelize`](https://www.npmjs.com/package/sequelize)
83+
-[`knex`](https://www.npmjs.com/package/knex)
84+
-[`typeorm`](https://www.npmjs.com/package/typeorm)
85+
-[`bookshelf`](https://www.npmjs.com/package/bookshelf)
86+
-[`drizzle-orm`](https://www.npmjs.com/package/drizzle-orm)
8787

8888
### API tools
8989

90-
*[`graphql`](https://www.npmjs.com/package/graphql) 15.x, 16.x
90+
-[`graphql`](https://www.npmjs.com/package/graphql) 15.x, 16.x
9191

9292
### Data serialization tools
9393

94-
*[`xml2js`](https://www.npmjs.com/package/xml2js) 0.6.x, 0.5.x, ^0.4.18
95-
*[`fast-xml-parser`](https://www.npmjs.com/package/fast-xml-parser) 5.x, 4.x
96-
*[`xml-js`](https://www.npmjs.com/package/xml-js) 1.x
94+
-[`xml2js`](https://www.npmjs.com/package/xml2js) 0.6.x, 0.5.x, ^0.4.18
95+
-[`fast-xml-parser`](https://www.npmjs.com/package/fast-xml-parser) 5.x, 4.x
96+
-[`xml-js`](https://www.npmjs.com/package/xml-js) 1.x
9797

9898
### Shell tools
9999

100-
*[`ShellJS`](https://www.npmjs.com/package/shelljs) 0.9.x, 0.8.x, 0.7.x
100+
-[`ShellJS`](https://www.npmjs.com/package/shelljs) 0.9.x, 0.8.x, 0.7.x
101101

102102
### Routers
103103

104-
*[`@koa/router`](https://www.npmjs.com/package/@koa/router) 14.x, 13.x, 12.x, 11.x and 10.x
104+
-[`@koa/router`](https://www.npmjs.com/package/@koa/router) 14.x, 13.x, 12.x, 11.x and 10.x
105105

106106
### AI SDKs
107107

108108
Zen instruments the following AI SDKs to track which models are used and how many tokens are consumed, allowing you to monitor your AI usage and costs:
109109

110-
*[`openai`](https://www.npmjs.com/package/openai) 5.x, 4.x
111-
*[`@mistralai/mistralai`](https://www.npmjs.com/package/@mistralai/mistralai) 1.x
112-
*[`@anthropic-ai/sdk`](https://www.npmjs.com/package/@anthropic-ai/sdk) ^0.40.x
113-
*[`@aws-sdk/client-bedrock-runtime`](https://www.npmjs.com/package/@aws-sdk/client-bedrock-runtime) 3.x
114-
*[`ai`](https://www.npmjs.com/package/ai) 5.x, 4.x
115-
*[`@google/genai`](https://www.npmjs.com/package/@google/genai) ^1.6.0
110+
-[`openai`](https://www.npmjs.com/package/openai) 5.x, 4.x
111+
-[`@mistralai/mistralai`](https://www.npmjs.com/package/@mistralai/mistralai) 1.x
112+
-[`@anthropic-ai/sdk`](https://www.npmjs.com/package/@anthropic-ai/sdk) ^0.40.x
113+
-[`@aws-sdk/client-bedrock-runtime`](https://www.npmjs.com/package/@aws-sdk/client-bedrock-runtime) 3.x
114+
-[`ai`](https://www.npmjs.com/package/ai) 5.x, 4.x
115+
-[`@google/genai`](https://www.npmjs.com/package/@google/genai) ^1.6.0
116116

117117
_Note: Prompt injection attacks are currently not covered by Zen._
118118

@@ -154,18 +154,18 @@ If an attack on your application is detected, we report immediately allowing you
154154

155155
You can easily select which IP addresses and/or bots to block from curated lists inside our Dashboard.
156156

157-
158157
You will need an Aikido account and a token to report events to Aikido. If you don't have an account, you can [sign up for free](https://app.aikido.dev/login). (No credit card required)
159158

160159
Here's how:
161-
* [Log in to your Aikido account](https://app.aikido.dev/login).
162-
* Go to [Zen](https://app.aikido.dev/runtime/services).
163-
* Go to apps.
164-
* Click on **Add app**.
165-
* Choose a name for your app.
166-
* Click **Generate token**.
167-
* Copy the token.
168-
* Set the token as an environment variable, `AIKIDO_TOKEN`, using [dotenv](https://github.com/motdotla/dotenv) or another method of your choosing.
160+
161+
- [Log in to your Aikido account](https://app.aikido.dev/login).
162+
- Go to [Zen](https://app.aikido.dev/runtime/services).
163+
- Go to apps.
164+
- Click on **Add app**.
165+
- Choose a name for your app.
166+
- Click **Generate token**.
167+
- Copy the token.
168+
- Set the token as an environment variable, `AIKIDO_TOKEN`, using [dotenv](https://github.com/motdotla/dotenv) or another method of your choosing.
169169

170170
## Running in production (blocking) mode
171171

@@ -185,7 +185,7 @@ This program is offered under a commercial and under the AGPL license.
185185
You can be released from the requirements of the AGPL license by purchasing
186186
a commercial license. Buying such a license is mandatory as soon as you
187187
develop commercial activities involving the Zen software without
188-
disclosing the source code of your own applications.
188+
disclosing the source code of your own applications.
189189

190190
For more information, please contact Aikido Security at this
191191
address: [email protected] or create an account at https://app.aikido.dev.

benchmarks/hono-pg/app/posts.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,21 @@ class Posts {
2020

2121
async add(title, text, authors) {
2222
const articleRes = await this.db.query(
23-
'INSERT INTO posts (title, text) VALUES ($1, $2) RETURNING id',
23+
"INSERT INTO posts (title, text) VALUES ($1, $2) RETURNING id",
2424
[title, text]
2525
);
2626

2727
const articleId = articleRes.rows[0].id;
2828

2929
for (const author of authors) {
3030
const authorExists = await this.db.query(
31-
'SELECT id FROM authors WHERE name = $1',
31+
"SELECT id FROM authors WHERE name = $1",
3232
[author]
3333
);
3434
let authorId;
3535
if (authorExists.rows.length === 0) {
3636
const authorRes = await this.db.query(
37-
'INSERT INTO authors (name) VALUES ($1) RETURNING id',
37+
"INSERT INTO authors (name) VALUES ($1) RETURNING id",
3838
[author]
3939
);
4040
authorId = authorRes.rows[0].id;
@@ -43,15 +43,15 @@ class Posts {
4343
}
4444

4545
await this.db.query(
46-
'INSERT INTO post_authors (post_id, author_id) VALUES ($1, $2)',
46+
"INSERT INTO post_authors (post_id, author_id) VALUES ($1, $2)",
4747
[articleId, authorId]
4848
);
4949
}
5050
}
5151

5252
async find(title) {
5353
const post = await this.db.query(
54-
'SELECT title, text FROM posts WHERE title = $1',
54+
"SELECT title, text FROM posts WHERE title = $1",
5555
[title]
5656
);
5757

docs/esm.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,22 @@ Alternatively, you can set the `NODE_OPTIONS` environment variable to include th
1515
export NODE_OPTIONS='-r @aikidosec/firewall/instrument'
1616
```
1717

18-
> [!IMPORTANT]
18+
> [!IMPORTANT]
1919
> Please also check the documentation on how to integrate Zen with your used web framework.
2020
21+
## Loading environment variables
22+
23+
When using `--require`/`-r` to preload the Zen firewall, the instrumentation hook runs before your application code. This means environment variables loaded by packages like `dotenv` will not be available when Zen starts.
24+
25+
To ensure `AIKIDO_TOKEN` and other environment variables are available during instrumentation, use Node.js's native `--env-file` flag:
26+
27+
```sh
28+
node --env-file=.env -r @aikidosec/firewall/instrument your-app.js
29+
```
30+
31+
> [!NOTE]
32+
> The `--env-file` flag cannot be used in `NODE_OPTIONS`.
33+
2134
## Known issues
2235

2336
- Zen can not protect ESM sub-dependencies of an ESM package. For example if an ESM package `foo` imports a sub-dependency `bar` that is also an ESM package, Zen will not be able to protect the code in `bar`. This is because the V8 engine does not allow Node.js to observe the evaluation of inner ESM packages (yet). Open issue: [Adding an evaluation hook for v8::Module](https://issues.chromium.org/u/1/issues/384413088). See a full example below.

docs/fastify.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,16 @@ async function authenticate(request, reply) {
8080
});
8181
}
8282

83-
fastify.get('/dashboard', {
84-
preHandler: [authenticate, Zen.fastifyHook],
85-
// ^ Add the Zen hook after your authentication logic
86-
}, async (request, reply) => {
87-
return { message: "Welcome to your dashboard!" };
88-
});
83+
fastify.get(
84+
"/dashboard",
85+
{
86+
preHandler: [authenticate, Zen.fastifyHook],
87+
// ^ Add the Zen hook after your authentication logic
88+
},
89+
async (request, reply) => {
90+
return { message: "Welcome to your dashboard!" };
91+
}
92+
);
8993
```
9094

9195
This approach allows user blocking and rate limiting to work properly when authentication runs in the `preHandler` stage where the request body is parsed.

0 commit comments

Comments
 (0)