Skip to content

Commit a42b9e2

Browse files
committed
Merge branch 'main' of github.com:AikidoSec/node-RASP into request-stats
* 'main' of github.com:AikidoSec/node-RASP: Prevent ReDoS Fix multiple control chars Remove unused code Check blocked users every time but log once Remove some comments Update comment Allow passing a Router to `addExpressMiddleware` Add comments Fix unit tests Fix path traversal in path Fix test file brackets Extend comment Add more tests Fix url path traversal bypass fix: Remove another ts-expect-error Remove unused @ts-expect-error Support Shelljs 0.9.x
2 parents 6f84655 + 916e44a commit a42b9e2

19 files changed

+580
-99
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ See list above for supported database drivers.
9292

9393
### Shell tools
9494

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

9797
### Routers
9898

docs/express.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,19 @@ Zen.addExpressMiddleware(app);
5959
app.get(...);
6060
```
6161

62+
You can also pass a `Router` instance to `Zen.addExpressMiddleware`:
63+
64+
```js
65+
const router = express.Router();
66+
67+
// Note: The middleware should be executed once per request
68+
Zen.addExpressMiddleware(router);
69+
70+
router.get(...);
71+
72+
app.use(router);
73+
```
74+
6275
## Debug mode
6376

6477
If you need to debug the firewall, you can run your express app with the environment variable `AIKIDO_DEBUG` set to `true`:

library/agent/Source.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const SOURCES = [
88
"xml",
99
"subdomains",
1010
"markUnsafe",
11+
"url",
1112
] as const;
1213

1314
export type Source = (typeof SOURCES)[number];

library/middleware/express.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/** TS_EXPECT_TYPES_ERROR_OPTIONAL_DEPENDENCY **/
2-
import type { Express } from "express";
2+
import type { Express, Router } from "express";
33
import { shouldBlockRequest } from "./shouldBlockRequest";
44
import { escapeHTML } from "../helpers/escapeHTML";
55

@@ -8,7 +8,7 @@ import { escapeHTML } from "../helpers/escapeHTML";
88
* Attacks will still be blocked by Zen if you do not call this function.
99
* Execute this function as early as possible in your Express app, but after the middleware that sets the user.
1010
*/
11-
export function addExpressMiddleware(app: Express) {
11+
export function addExpressMiddleware(app: Express | Router) {
1212
app.use((req, res, next) => {
1313
const result = shouldBlockRequest();
1414

library/middleware/shouldBlockRequest.test.ts

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,23 @@ const sampleContext: Context = {
1919
route: "/posts/:id",
2020
};
2121

22-
t.test("without context", async (t) => {
23-
const logs: string[] = [];
24-
wrap(console, "warn", function warn() {
25-
return function warn(message: string) {
26-
logs.push(message);
27-
};
28-
});
22+
let logs: string[] = [];
23+
wrap(console, "warn", function warn() {
24+
return function warn(message: string) {
25+
logs.push(message);
26+
};
27+
});
2928

29+
t.beforeEach(() => {
30+
logs = [];
31+
});
32+
33+
t.test("without context", async (t) => {
3034
const result = shouldBlockRequest();
3135
shouldBlockRequest();
3236
t.same(result, { block: false });
3337
t.same(logs, [
34-
"shouldBlockRequest() was called without a context. The request will not be blocked. Make sure to call shouldBlockRequest() within an HTTP request. If you're using serverless functions, make sure to use the handler wrapper provided by Zen. Also ensure you import Zen at the top of your main app file (before any other imports).",
38+
"Zen.shouldBlockRequest() was called without a context. The request will not be blocked. Make sure to call shouldBlockRequest() within an HTTP request. If you're using serverless functions, make sure to use the handler wrapper provided by Zen. Also ensure you import Zen at the top of your main app file (before any other imports).",
3539
]);
3640
});
3741

@@ -47,3 +51,14 @@ t.test("with agent", async (t) => {
4751
t.same(shouldBlockRequest(), { block: false });
4852
});
4953
});
54+
55+
t.test("multiple calls", async (t) => {
56+
createTestAgent();
57+
runWithContext(sampleContext, () => {
58+
shouldBlockRequest();
59+
shouldBlockRequest();
60+
});
61+
t.same(logs, [
62+
"Zen.shouldBlockRequest() was called multiple times. The middleware should be executed once per request.",
63+
]);
64+
});

library/middleware/shouldBlockRequest.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ export function shouldBlockRequest(): Result {
2121
return { block: false };
2222
}
2323

24+
if (context.executedMiddleware) {
25+
logWarningAlreadyExecutedMiddleware();
26+
}
27+
2428
updateContext(context, "executedMiddleware", true);
2529
agent.onMiddlewareExecuted();
2630

@@ -50,8 +54,23 @@ function logWarningShouldBlockRequestCalledWithoutContext() {
5054

5155
// eslint-disable-next-line no-console
5256
console.warn(
53-
"shouldBlockRequest() was called without a context. The request will not be blocked. Make sure to call shouldBlockRequest() within an HTTP request. If you're using serverless functions, make sure to use the handler wrapper provided by Zen. Also ensure you import Zen at the top of your main app file (before any other imports)."
57+
"Zen.shouldBlockRequest() was called without a context. The request will not be blocked. Make sure to call shouldBlockRequest() within an HTTP request. If you're using serverless functions, make sure to use the handler wrapper provided by Zen. Also ensure you import Zen at the top of your main app file (before any other imports)."
5458
);
5559

5660
loggedWarningShouldBlockRequestCalledWithoutContext = true;
5761
}
62+
63+
let loggedWarningAlreadyExecutedMiddleware = false;
64+
65+
function logWarningAlreadyExecutedMiddleware() {
66+
if (loggedWarningAlreadyExecutedMiddleware) {
67+
return;
68+
}
69+
70+
// eslint-disable-next-line no-console
71+
console.warn(
72+
"Zen.shouldBlockRequest() was called multiple times. The middleware should be executed once per request."
73+
);
74+
75+
loggedWarningAlreadyExecutedMiddleware = true;
76+
}

0 commit comments

Comments
 (0)