Skip to content

Commit 44ca2e2

Browse files
committed
add taint-step to XML parsers
1 parent 1c43505 commit 44ca2e2

File tree

3 files changed

+33
-3
lines changed

3 files changed

+33
-3
lines changed

javascript/ql/src/semmle/javascript/frameworks/XmlParsers.qll

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ module XML {
2525

2626
/** Holds if this call to the XML parser resolves entities of the given `kind`. */
2727
abstract predicate resolvesEntities(EntityKind kind);
28+
29+
/** Gets a reference to a value resulting from parsing the XML. */
30+
js::DataFlow::Node getAResult() { none() }
2831
}
2932

3033
/**
@@ -98,10 +101,11 @@ module XML {
98101
* An invocation of `expat.Parser.parse` or `expat.Parser.write`.
99102
*/
100103
class ExpatParserInvocation extends ParserInvocation {
104+
js::DataFlow::NewNode parser;
105+
101106
ExpatParserInvocation() {
102-
exists(string m | m = "parse" or m = "write" |
103-
this = moduleMethodCall("node-expat", "Parser", m)
104-
)
107+
parser = js::DataFlow::moduleMember("node-expat", "Parser").getAnInstantiation() and
108+
this = parser.getAMemberCall(["parse", "write"]).asExpr()
105109
}
106110

107111
override js::Expr getSourceArgument() { result = getArgument(0) }
@@ -110,6 +114,10 @@ module XML {
110114
// only internal entities are resolved by default
111115
kind = InternalEntity()
112116
}
117+
118+
override js::DataFlow::Node getAResult() {
119+
result = parser.getAMemberCall("on").getABoundCallbackParameter(1, _)
120+
}
113121
}
114122

115123
/**
@@ -160,4 +168,15 @@ module XML {
160168

161169
override predicate resolvesEntities(XML::EntityKind kind) { kind = InternalEntity() }
162170
}
171+
172+
private class XMLParserTaintStep extends js::TaintTracking::AdditionalTaintStep {
173+
XML::ParserInvocation parser;
174+
175+
XMLParserTaintStep() { this.asExpr() = parser }
176+
177+
override predicate step(js::DataFlow::Node pred, js::DataFlow::Node succ) {
178+
pred.asExpr() = parser.getSourceArgument() and
179+
succ = parser.getAResult()
180+
}
181+
}
163182
}

javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,4 @@ typeInferenceMismatch
145145
| tst.js:2:13:2:20 | source() | tst.js:45:10:45:24 | x.map(x2 => x2) |
146146
| tst.js:2:13:2:20 | source() | tst.js:47:10:47:30 | Buffer. ... 'hex') |
147147
| tst.js:2:13:2:20 | source() | tst.js:48:10:48:22 | new Buffer(x) |
148+
| xml.js:5:18:5:25 | source() | xml.js:8:14:8:17 | text |
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
(function () {
2+
var Parser = require("node-expat").Parser
3+
var parser = new Parser();
4+
5+
parser.write(source());
6+
7+
parser.on("text", text => {
8+
sink(text); // NOT OK
9+
});
10+
})();

0 commit comments

Comments
 (0)