Skip to content

Commit 1792c9a

Browse files
committed
add taint step through the prettyjson library
1 parent 0bfff1e commit 1792c9a

File tree

4 files changed

+48
-1
lines changed

4 files changed

+48
-1
lines changed

javascript/change-notes/2021-06-24-json.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ lgtm,codescanning
22
* The dataflow libraries now model dataflow through more JSON utility libraries.
33
Affected packages are
44
[json2csv](https://npmjs.com/package/json2csv),
5-
[json5](https://npmjs.com/package/json5)
5+
[json5](https://npmjs.com/package/json5),
6+
[prettyjson](https://npmjs.com/package/prettyjson)

javascript/ql/src/semmle/javascript/JsonStringifiers.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,19 @@ class JSON2CSVTaintStep extends TaintTracking::SharedTaintStep {
5353
)
5454
}
5555
}
56+
57+
/**
58+
* A step through the [`prettyjson`](https://www.npmjs.com/package/prettyjson) library.
59+
* This is not quite a `JSON.stringify` call, as it e.g. does not wrap keys in double quotes.
60+
* It's therefore modelled as a taint-step rather than as a `JSON.stringify` call.
61+
*/
62+
class PrettyJSONTaintStep extends TaintTracking::SharedTaintStep {
63+
override predicate step(DataFlow::Node pred, DataFlow::Node succ) {
64+
exists(API::CallNode call |
65+
call = API::moduleImport("prettyjson").getMember("render").getACall()
66+
|
67+
pred = call.getArgument(0) and
68+
succ = call
69+
)
70+
}
71+
}

javascript/ql/test/query-tests/Security/CWE-117/LogInjection.expected

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ nodes
6565
| logInjectionBad.js:58:17:58:59 | stripAn ... rname)) |
6666
| logInjectionBad.js:58:27:58:58 | chalk.u ... ername) |
6767
| logInjectionBad.js:58:50:58:57 | username |
68+
| logInjectionBad.js:63:9:63:36 | q |
69+
| logInjectionBad.js:63:13:63:36 | url.par ... , true) |
70+
| logInjectionBad.js:63:23:63:29 | req.url |
71+
| logInjectionBad.js:63:23:63:29 | req.url |
72+
| logInjectionBad.js:64:9:64:35 | username |
73+
| logInjectionBad.js:64:20:64:20 | q |
74+
| logInjectionBad.js:64:20:64:26 | q.query |
75+
| logInjectionBad.js:64:20:64:35 | q.query.username |
76+
| logInjectionBad.js:66:17:66:43 | prettyj ... ername) |
77+
| logInjectionBad.js:66:17:66:43 | prettyj ... ername) |
78+
| logInjectionBad.js:66:35:66:42 | username |
6879
edges
6980
| logInjectionBad.js:19:9:19:36 | q | logInjectionBad.js:20:20:20:20 | q |
7081
| logInjectionBad.js:19:13:19:36 | url.par ... , true) | logInjectionBad.js:19:9:19:36 | q |
@@ -130,6 +141,16 @@ edges
130141
| logInjectionBad.js:58:27:58:58 | chalk.u ... ername) | logInjectionBad.js:58:17:58:59 | stripAn ... rname)) |
131142
| logInjectionBad.js:58:27:58:58 | chalk.u ... ername) | logInjectionBad.js:58:17:58:59 | stripAn ... rname)) |
132143
| logInjectionBad.js:58:50:58:57 | username | logInjectionBad.js:58:27:58:58 | chalk.u ... ername) |
144+
| logInjectionBad.js:63:9:63:36 | q | logInjectionBad.js:64:20:64:20 | q |
145+
| logInjectionBad.js:63:13:63:36 | url.par ... , true) | logInjectionBad.js:63:9:63:36 | q |
146+
| logInjectionBad.js:63:23:63:29 | req.url | logInjectionBad.js:63:13:63:36 | url.par ... , true) |
147+
| logInjectionBad.js:63:23:63:29 | req.url | logInjectionBad.js:63:13:63:36 | url.par ... , true) |
148+
| logInjectionBad.js:64:9:64:35 | username | logInjectionBad.js:66:35:66:42 | username |
149+
| logInjectionBad.js:64:20:64:20 | q | logInjectionBad.js:64:20:64:26 | q.query |
150+
| logInjectionBad.js:64:20:64:26 | q.query | logInjectionBad.js:64:20:64:35 | q.query.username |
151+
| logInjectionBad.js:64:20:64:35 | q.query.username | logInjectionBad.js:64:9:64:35 | username |
152+
| logInjectionBad.js:66:35:66:42 | username | logInjectionBad.js:66:17:66:43 | prettyj ... ername) |
153+
| logInjectionBad.js:66:35:66:42 | username | logInjectionBad.js:66:17:66:43 | prettyj ... ername) |
133154
#select
134155
| logInjectionBad.js:22:18:22:43 | `[INFO] ... rname}` | logInjectionBad.js:19:23:19:29 | req.url | logInjectionBad.js:22:18:22:43 | `[INFO] ... rname}` | $@ flows to log entry. | logInjectionBad.js:19:23:19:29 | req.url | User-provided value |
135156
| logInjectionBad.js:23:37:23:44 | username | logInjectionBad.js:19:23:19:29 | req.url | logInjectionBad.js:23:37:23:44 | username | $@ flows to log entry. | logInjectionBad.js:19:23:19:29 | req.url | User-provided value |
@@ -146,3 +167,4 @@ edges
146167
| logInjectionBad.js:56:17:56:55 | kleur.b ... ername) | logInjectionBad.js:46:23:46:29 | req.url | logInjectionBad.js:56:17:56:55 | kleur.b ... ername) | $@ flows to log entry. | logInjectionBad.js:46:23:46:29 | req.url | User-provided value |
147168
| logInjectionBad.js:57:17:57:48 | chalk.u ... ername) | logInjectionBad.js:46:23:46:29 | req.url | logInjectionBad.js:57:17:57:48 | chalk.u ... ername) | $@ flows to log entry. | logInjectionBad.js:46:23:46:29 | req.url | User-provided value |
148169
| logInjectionBad.js:58:17:58:59 | stripAn ... rname)) | logInjectionBad.js:46:23:46:29 | req.url | logInjectionBad.js:58:17:58:59 | stripAn ... rname)) | $@ flows to log entry. | logInjectionBad.js:46:23:46:29 | req.url | User-provided value |
170+
| logInjectionBad.js:66:17:66:43 | prettyj ... ername) | logInjectionBad.js:63:23:63:29 | req.url | logInjectionBad.js:66:17:66:43 | prettyj ... ername) | $@ flows to log entry. | logInjectionBad.js:63:23:63:29 | req.url | User-provided value |

javascript/ql/test/query-tests/Security/CWE-117/logInjectionBad.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,12 @@ const server2 = http.createServer((req, res) => {
5656
console.log(kleur.blue().bold().underline(username)); // NOT OK
5757
console.log(chalk.underline.bgBlue(username)); // NOT OK
5858
console.log(stripAnsi(chalk.underline.bgBlue(username))); // NOT OK
59+
});
60+
61+
var prettyjson = require('prettyjson');
62+
const server3 = http.createServer((req, res) => {
63+
let q = url.parse(req.url, true);
64+
let username = q.query.username;
65+
66+
console.log(prettyjson.render(username)); // NOT OK
5967
});

0 commit comments

Comments
 (0)