Skip to content

Commit aa35380

Browse files
committed
WIP
1 parent bae359e commit aa35380

3 files changed

Lines changed: 49 additions & 51 deletions

File tree

.codeclimate.yml

Lines changed: 0 additions & 51 deletions
This file was deleted.

app/app.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { randomBytes } from 'crypto';
99

1010
import { version as appVersion } from './package.json';
1111
import { getLogger, httpLogger } from './src/components/log';
12+
import { requestSanitizer } from './src/middleware/requestSanitizer';
1213
import router from './src/routes';
1314
import { Problem } from './src/utils';
1415
import { DEFAULTCORS } from './src/utils/constants/application';
@@ -26,6 +27,7 @@ app.use(compression());
2627
app.use(cors(DEFAULTCORS));
2728
app.use(express.json({ limit: config.get('server.bodyLimit') }));
2829
app.use(express.urlencoded({ extended: true }));
30+
app.use(requestSanitizer());
2931
app.set('query parser', 'extended');
3032

3133
app.use((_req, res, next) => {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import type { NextFunction, Request, Response } from 'express';
2+
3+
/** Remove all NUL characters from a string. */
4+
export function stripNullsFromString(input: string): string {
5+
// Fast path: avoid allocation when there's nothing to replace
6+
return input.indexOf('\u0000') === -1 ? input : input.replace(/[\x00]/g, '');
7+
}
8+
9+
function isPlainObject(value: unknown): value is Record<string, unknown> {
10+
return typeof value === 'object' && value !== null && !Array.isArray(value);
11+
}
12+
13+
/**
14+
* @function sanitizeDeep
15+
* Recursively sanitize JSON-like data (strings, arrays, plain objects).
16+
* @param value - The value to sanitize.
17+
* @returns The sanitized value.
18+
*/
19+
function sanitizeDeep(value: unknown): unknown {
20+
// Strip NUL characters from strings
21+
if (typeof value === 'string') return stripNullsFromString(value);
22+
23+
// Recursively sanitize arrays items
24+
if (Array.isArray(value)) return value.map(sanitizeDeep);
25+
26+
// Recursively sanitize plain objects
27+
if (typeof value === 'object' && value !== null) {
28+
const out: Record<string, unknown> = {};
29+
for (const [k, v] of Object.entries(value)) out[k] = sanitizeDeep(v);
30+
return out;
31+
}
32+
return value;
33+
}
34+
35+
/**
36+
* @function requestSanitizer
37+
* @description Express middleware to sanitize incoming request bodies.
38+
* @param req - The Express request object.
39+
* @param _res - The Express response object.
40+
* @param next - The next middleware function.
41+
*/
42+
export function requestSanitizer(req: Request, _res: Response, next: NextFunction): void {
43+
if (typeof req.body !== 'undefined') {
44+
req.body = sanitizeDeep(req.body) as typeof req.body;
45+
}
46+
next();
47+
}

0 commit comments

Comments
 (0)