Skip to content

Commit bfa7553

Browse files
committed
Python: urlsplit sanitizer handles in [KNOWN_VALUE]
1 parent 798db91 commit bfa7553

File tree

3 files changed

+23
-6
lines changed

3 files changed

+23
-6
lines changed

python/ql/src/semmle/python/security/strings/External.qll

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,8 @@ class UrlsplitUrlparseTempSanitizer extends Sanitizer {
230230
private predicate clears_taint(ControlFlowNode final_test, ControlFlowNode tainted, ControlFlowNode test, boolean sense) {
231231
test_equality_with_const(final_test, tainted, sense)
232232
or
233+
test_in_const_seq(final_test, tainted, sense)
234+
or
233235
test.(UnaryExprNode).getNode().getOp() instanceof Not and
234236
exists(ControlFlowNode nested_test |
235237
nested_test = test.(UnaryExprNode).getOperand() and
@@ -238,19 +240,34 @@ class UrlsplitUrlparseTempSanitizer extends Sanitizer {
238240
}
239241

240242
/** holds for `== "KNOWN_VALUE"` on `true` edge, and `!= "KNOWN_VALUE"` on `false` edge */
241-
private predicate test_equality_with_const(CompareNode cmp, ControlFlowNode operand, boolean sense) {
243+
private predicate test_equality_with_const(CompareNode cmp, ControlFlowNode tainted, boolean sense) {
242244
exists(ControlFlowNode const, Cmpop op |
243245
const.getNode() instanceof StrConst
244246
|
245247
(
246-
cmp.operands(const, op, operand)
248+
cmp.operands(const, op, tainted)
247249
or
248-
cmp.operands(operand, op, const)
249-
) and (
250+
cmp.operands(tainted, op, const)
251+
) and
252+
(
250253
op instanceof Eq and sense = true
251254
or
252255
op instanceof NotEq and sense = false
253256
)
254257
)
255258
}
259+
260+
/** holds for `in ["KNOWN_VALUE", ...]` on `true` edge, and `not in ["KNOWN_VALUE", ...]` on `false` edge */
261+
private predicate test_in_const_seq(CompareNode cmp, ControlFlowNode tainted, boolean sense) {
262+
exists(SequenceNode const_seq, Cmpop op |
263+
forall(ControlFlowNode elem | elem = const_seq.getAnElement() | elem.getNode() instanceof StrConst)
264+
|
265+
cmp.operands(tainted, op, const_seq) and
266+
(
267+
op instanceof In and sense = true
268+
or
269+
op instanceof NotIn and sense = false
270+
)
271+
)
272+
}
256273
}

python/ql/test/library-tests/taint/namedtuple/TestTaint.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
| test.py:20 | test_sanitizer | Attribute | NO TAINT |
77
| test.py:23 | test_sanitizer | Subscript | NO TAINT |
88
| test.py:26 | test_sanitizer | Attribute | NO TAINT |
9-
| test.py:29 | test_sanitizer | Attribute | externally controlled string |
9+
| test.py:29 | test_sanitizer | Attribute | NO TAINT |
1010
| test.py:32 | test_sanitizer | Attribute | externally controlled string |
1111
| test.py:42 | test_namedtuple | a | NO TAINT |
1212
| test.py:42 | test_namedtuple | b | NO TAINT |

python/ql/test/library-tests/taint/namedtuple/test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def test_sanitizer():
2626
test(urlsplit_res.path) # FN
2727

2828
if urlsplit_res.netloc in ["OK"]:
29-
test(urlsplit_res.netloc) # FP
29+
test(urlsplit_res.netloc)
3030

3131
if urlsplit_res.netloc in ["OK", non_constant()]:
3232
test(urlsplit_res.netloc) # should be tainted

0 commit comments

Comments
 (0)