Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bd1c99d

Browse files
author
Max Schaefer
committed
JavaScript: Recognise JSON.stringify and JSON.parse as escaper/unescaper.
1 parent 63f2447 commit bd1c99d

3 files changed

Lines changed: 68 additions & 0 deletions

File tree

javascript/ql/src/Security/CWE-116/DoubleEscaping.ql

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,52 @@ class GlobalStringReplacement extends Replacement, DataFlow::MethodCallNode {
167167
}
168168
}
169169

170+
/**
171+
* A call to `JSON.stringify`, viewed as a string replacement.
172+
*/
173+
class JsonStringifyReplacement extends Replacement, DataFlow::CallNode {
174+
JsonStringifyReplacement() {
175+
this = DataFlow::globalVarRef("JSON").getAMemberCall("stringify")
176+
}
177+
178+
override predicate replaces(string input, string output) {
179+
input = "\\" and output = "\\\\"
180+
// the other replacements are not relevant for this query
181+
}
182+
183+
override DataFlow::Node getInput() {
184+
result = this.getArgument(0)
185+
}
186+
187+
override DataFlow::SourceNode getOutput() {
188+
result = this
189+
}
190+
}
191+
192+
/**
193+
* A call to `JSON.parse`, viewed as a string replacement.
194+
*/
195+
class JsonParseReplacement extends Replacement {
196+
JsonParserCall self;
197+
198+
JsonParseReplacement() {
199+
this = self
200+
}
201+
202+
override predicate replaces(string input, string output) {
203+
input = "\\\\" and output = "\\"
204+
// the other replacements are not relevant for this query
205+
}
206+
207+
override DataFlow::Node getInput() {
208+
result = self.getInput()
209+
}
210+
211+
override DataFlow::SourceNode getOutput() {
212+
result = self.getOutput()
213+
}
214+
}
215+
170216
from Replacement primary, Replacement supplementary, string message, string metachar
171217
where
172218
primary.escapes(metachar, _) and

javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@
55
| tst.js:53:10:53:33 | s.repla ... , '\\\\') | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:53:10:54:33 | s.repla ... , '\\'') | here |
66
| tst.js:60:7:60:28 | s.repla ... '%25') | This replacement may double-escape '%' characters from $@. | tst.js:59:7:59:28 | s.repla ... '%26') | here |
77
| tst.js:68:10:70:38 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:68:10:69:39 | s.repla ... apos;") | here |
8+
| tst.js:74:10:77:10 | JSON.st ... ) | This replacement may double-escape '\\' characters from $@. | tst.js:75:12:76:37 | s.repla ... u003E") | here |
9+
| tst.js:86:10:86:22 | JSON.parse(s) | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:86:10:86:47 | JSON.pa ... g, "<") | here |

javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,23 @@ function badEncode(s) {
6969
.replace(indirect2, "&apos;")
7070
.replace(indirect3, "&amp;");
7171
}
72+
73+
function badEscape1(s) {
74+
return JSON.stringify(
75+
s.replace(/</g, "\\u003C")
76+
.replace(/>/g, "\\u003E")
77+
);
78+
}
79+
80+
function goodEscape1(s) {
81+
return JSON.stringify(s)
82+
.replace(/</g, "\\u003C").replace(/>/g, "\\u003E");
83+
}
84+
85+
function badUnescape2(s) {
86+
return JSON.parse(s).replace(/\\u003C/g, "<").replace(/\\u003E/g, ">");
87+
}
88+
89+
function goodUnescape2(s) {
90+
return JSON.parse(s.replace(/\\u003C/g, "<").replace(/\\u003E/g, ">"));
91+
}

0 commit comments

Comments
 (0)