Skip to content

Commit 3c9e50a

Browse files
committed
Allow replacement of prohibited characters, instead of removing data
1 parent 10d865c commit 3c9e50a

File tree

3 files changed

+406
-138
lines changed

3 files changed

+406
-138
lines changed

README.md

+17-3
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,33 @@ var app = express();
2121

2222
app.use(bodyParser.urlencoded({extended: true}));
2323
app.use(bodyParser.json());
24+
25+
// To remove data, use:
2426
app.use(mongoSanitize());
2527

28+
// Or, to replace prohibited characters with _, use:
29+
app.use(mongoSanitize({
30+
replaceWith: '_'
31+
}))
32+
2633
```
2734

2835
## What?
2936

30-
This module removes any keys in objects that begin with a `$` sign from `req.body`, `req.query` or `req.params`.
37+
This module searches for any keys in objects that begin with a `$` sign or contain a `.`, from `req.body`, `req.query` or `req.params`. It can then either:
38+
39+
- completely remove these keys and associated data from the object, or
40+
- replace the prohibited characters with another allowed character.
41+
42+
The behaviour is governed by the passed option, `replaceWith`. Set this option to have the sanitizer replace the prohibited characters with the character passed in.
43+
44+
See the spec file for more examples.
3145

3246
## Why?
3347

34-
Object keys starting with a `$` are _reserved_ for use by MongoDB as operators. Without this sanitization, malicious users could send an object containing a `$` operator, which could change the context of a database operation. Most notorious is the `$where` operator, which can execute arbitrary JavaScript on the database.
48+
Object keys starting with a `$` or containing a `.` are _reserved_ for use by MongoDB as operators. Without this sanitization, malicious users could send an object containing a `$` operator, or including a `.`, which could change the context of a database operation. Most notorious is the `$where` operator, which can execute arbitrary JavaScript on the database.
3549

36-
The best way to prevent this is to sanitize the received data, and remove any offending keys.
50+
The best way to prevent this is to sanitize the received data, and remove any offending keys, or replace the characters with a 'safe' one.
3751

3852
## Credits
3953

index.js

+39-16
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,52 @@
11
'use strict';
22

3-
var sanitize = function(val) {
4-
if(Array.isArray(val)) {
5-
val.forEach(sanitize);
6-
7-
} else if(val instanceof Object) {
8-
Object.keys(val).forEach(function(key) {
9-
if (/^\$|\./.test(key)) {
10-
delete val[key];
11-
} else {
12-
sanitize(val[key]);
13-
}
14-
});
3+
var TEST_REGEX = /^\$|\./,
4+
REPLACE_REGEX = /^\$|\./g;
5+
6+
var sanitize = function(val, options) {
7+
options = options || {};
8+
9+
var replaceWith = null;
10+
if(!(TEST_REGEX.test(options.replaceWith))) {
11+
replaceWith = options.replaceWith;
1512
}
1613

17-
return val;
14+
var act = function(val) {
15+
if(Array.isArray(val)) {
16+
val.forEach(act);
17+
18+
} else if(val instanceof Object) {
19+
Object.keys(val).forEach(function(key) {
20+
var v = val[key];
21+
var noRecurse = false;
22+
23+
if(TEST_REGEX.test(key)) {
24+
delete val[key];
25+
if(replaceWith) {
26+
val[key.replace(REPLACE_REGEX, replaceWith)] = v;
27+
} else {
28+
noRecurse = true;
29+
}
30+
}
31+
32+
if(!noRecurse) {
33+
act(v);
34+
}
35+
36+
});
37+
}
38+
39+
return val;
40+
};
41+
42+
return act(val);
1843
};
1944

2045
var middleware = function(options) {
21-
options = options || {};
22-
2346
return function(req, res, next) {
2447
['body', 'params', 'query'].forEach(function(k) {
2548
if(req[k]) {
26-
req[k] = sanitize(req[k]);
49+
req[k] = sanitize(req[k], options);
2750
}
2851
});
2952
next();

0 commit comments

Comments
 (0)