Conversation
…orgery/test_azure_client.py Co-authored-by: Copilot <[email protected]>
…orgery/test_azure_client.py Co-authored-by: Copilot <[email protected]>
…caes to use postprocessing results. Currently results for partial ssrf still need work, it is flagging cases where the URL is fully controlled, but is sanitized. I'm not sure if this should be flagged yet.
There was a problem hiding this comment.
Pull request overview
This PR updates the Python SSRF (CWE-918) query tests to use inline-expectations postprocessing and adds modeling/tests for the AntiSSRF library’s URI validation as a sanitizer for full URL control.
Changes:
- Migrate SSRF query-tests to
utils/test/InlineExpectationsTestQuery.qlpostprocessing. - Expand SSRF test coverage for
requests,http.client, Azure SDK sinks, and new AntiSSRF validation APIs. - Add an AntiSSRF
URIValidatorbarrier/sanitizer to SSRF dataflow customizations and record the change in change notes.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 15 comments.
Show a summary per file
| File | Description |
|---|---|
| python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_requests.py | Adds more requests SSRF cases and AntiSSRFPolicy-based safe/unsafe session scenarios with inline expectations. |
| python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py | New tests covering AntiSSRF URIValidator domain checks and how they interact with SSRF sink classification. |
| python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_http_client.py | Updates http.client SSRF tests to inline expectations and adds sink annotations. |
| python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py | Converts Azure SSRF sink tests to inline expectations and simplifies call formatting. |
| python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/full_partial_test.py | Refactors existing full/partial SSRF test cases to inline expectations and adds explicit alert annotations. |
| python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.qlref | Switches to query:/postprocess: format to enable inline expectations postprocessing. |
| python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.expected | Regenerated expected output for postprocessed partial SSRF tests. |
| python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.qlref | Switches to query:/postprocess: format to enable inline expectations postprocessing. |
| python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/FullServerSideRequestForgery.expected | Regenerated expected output for postprocessed full SSRF tests. |
| python/ql/lib/semmle/python/security/dataflow/ServerSideRequestForgeryCustomizations.qll | Adds AntiSSRF URIValidator barrier/guard modeling for full URL control sanitization. |
| python/ql/lib/change-notes/2026-02-09-ssrf_test_case_cleanup_and_new_ssrf_barriers.md | Documents the SSRF test cleanup and new AntiSSRF barrier behavior. |
Comments suppressed due to low confidence (47)
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:21
- Variable c is not used.
c = SecretClient(vault_url=full_url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:35
- Variable c is not used.
c = KeyClient(vault_url=full_url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:37
- Variable c is not used.
c = KeyClient(vault_url=full_url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:51
- Variable c is not used.
c = ShareFileClient.from_file_url(full_url) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:53
- Variable c is not used.
c = ShareFileClient.from_file_url(full_url) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:130
- Variable c is not used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:132
- Variable c is not used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_requests.py:29
- Variable response is not used.
response = session.get(user_input)
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_requests.py:39
- Variable response is not used.
response = session.get(user_input) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_requests.py:49
- Variable response is not used.
response = session.get(user_input) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py:16
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=full_url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py:17
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = ShareFileClient.from_file_url(url) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py:18
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = ShareFileClient.from_file_url(full_url) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py:19
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = KeyClient(url, credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py:20
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = KeyClient(full_url, credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py:21
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = ContainerClient.from_container_url(container_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:16
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:30
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = KeyClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:32
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = KeyClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:46
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = ShareFileClient.from_file_url(url) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:48
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = ShareFileClient.from_file_url(url) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:64
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:66
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:69
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:71
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:74
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:76
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:79
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:81
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:85
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:87
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:90
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:92
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:95
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:97
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:100
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:102
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:105
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:107
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:110
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:112
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:115
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:117
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:120
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:122
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:125
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/full-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py:127
- This assignment to 'c' is unnecessary as it is redefined before this value is used.
This assignment to 'c' is unnecessary as it is redefined before this value is used.
c = SecretClient(vault_url=url, credential=credential) # $ Alert[py/partial-ssrf]
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py
Outdated
Show resolved
Hide resolved
python/ql/lib/semmle/python/security/dataflow/ServerSideRequestForgeryCustomizations.qll
Outdated
Show resolved
Hide resolved
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_requests.py
Outdated
Show resolved
Hide resolved
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_requests.py
Outdated
Show resolved
Hide resolved
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_requests.py
Outdated
Show resolved
Hide resolved
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py
Outdated
Show resolved
Hide resolved
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py
Outdated
Show resolved
Hide resolved
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_requests.py
Outdated
Show resolved
Hide resolved
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_azure_client.py
Outdated
Show resolved
Hide resolved
python/ql/test/query-tests/Security/CWE-918-ServerSideRequestForgery/test_path_validation.py
Outdated
Show resolved
Hide resolved
…orgery/test_path_validation.py Co-authored-by: Copilot <[email protected]>
…esults (column numbers).
owen-mc
left a comment
There was a problem hiding this comment.
I haven't finished looking at this yet.
| @@ -1 +1,2 @@ | |||
| Security/CWE-918/FullServerSideRequestForgery.ql | |||
| query: Security/CWE-918/FullServerSideRequestForgery.ql | |||
| postprocess: utils/test/InlineExpectationsTestQuery.ql No newline at end of file | |||
There was a problem hiding this comment.
We should also pretty-print the models. If we don't do this then someone adding an unrelated model in future will change the numbering of the models in this test and hence the expected output, which is very confusing.
| postprocess: utils/test/InlineExpectationsTestQuery.ql | |
| postprocess: | |
| - utils/test/PrettyPrintModels.ql | |
| - utils/test/InlineExpectationsTestQuery.ql |
You'll have to update the test output as well.
.../query-tests/Security/CWE-918-ServerSideRequestForgery/PartialServerSideRequestForgery.qlref
Outdated
Show resolved
Hide resolved
| // validator used in a comparison | ||
| exists(CompareNode cn, Cmpop op, Node n | cn = g and n.getALocalSource() = call | | ||
| ( | ||
| // validator == true or validator == false or validator is True or validator is False | ||
| (op instanceof Eq or op instanceof Is) and | ||
| exists(ControlFlowNode l, boolean bool | | ||
| l.getNode().(BooleanLiteral).booleanValue() = bool and | ||
| bool in [true, false] and | ||
| branch = bool and | ||
| cn.operands(n.asCfgNode(), op, l) | ||
| ) | ||
| or | ||
| // validator != false or validator != true or validator is not True or validator is not False | ||
| (op instanceof NotEq or op instanceof IsNot) and | ||
| exists(ControlFlowNode l, boolean bool | | ||
| l.getNode().(BooleanLiteral).booleanValue() = bool and | ||
| bool in [true, false] and | ||
| branch = bool.booleanNot() and | ||
| cn.operands(n.asCfgNode(), op, l) | ||
| ) | ||
| ) | ||
| ) | ||
| or | ||
| // validator call directly (e.g., if URIValidator.in_domain(...) ) | ||
| g = call.asCfgNode() and | ||
| branch = true |
There was a problem hiding this comment.
I agree, it's awkward. The present solution is an okay band-aid (especially after some cleanup), but it would be nice to have a generic solution that could also account for things like boolean operators, etc.
I think the closest thing I'm aware of is https://github.com/github/codeql/blob/main/python/ql/lib/semmle/python/Comparisons.qll
but this is very much aimed at a particular kind of comparison, and would not be immediately applicable here.
|
I finished reviewing. The tests cover all the new sanitizers, which is good. My only remaining issue is around whether the sanitizer guard definition needs all the logic around different kinds of comparisons. |
tausbn
left a comment
There was a problem hiding this comment.
A few suggestions, otherwise this looks good to me. 👍
| private predicate uri_validator(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) { | ||
| exists(DataFlow::CallCfgNode call, string funcs | | ||
| funcs in ["in_domain", "in_azure_keyvault_domain", "in_azure_storage_domain"] | ||
| | | ||
| call = API::moduleImport("AntiSSRF").getMember("URIValidator").getMember(funcs).getACall() and | ||
| call.getArg(0).asCfgNode() = node and | ||
| ( | ||
| // validator used in a comparison | ||
| exists(CompareNode cn, Cmpop op, Node n | cn = g and n.getALocalSource() = call | | ||
| ( | ||
| // validator == true or validator == false or validator is True or validator is False | ||
| (op instanceof Eq or op instanceof Is) and | ||
| exists(ControlFlowNode l, boolean bool | | ||
| l.getNode().(BooleanLiteral).booleanValue() = bool and | ||
| bool in [true, false] and | ||
| branch = bool and | ||
| cn.operands(n.asCfgNode(), op, l) | ||
| ) | ||
| or | ||
| // validator != false or validator != true or validator is not True or validator is not False | ||
| (op instanceof NotEq or op instanceof IsNot) and | ||
| exists(ControlFlowNode l, boolean bool | | ||
| l.getNode().(BooleanLiteral).booleanValue() = bool and | ||
| bool in [true, false] and | ||
| branch = bool.booleanNot() and | ||
| cn.operands(n.asCfgNode(), op, l) | ||
| ) | ||
| ) | ||
| ) | ||
| or | ||
| // validator call directly (e.g., if URIValidator.in_domain(...) ) | ||
| g = call.asCfgNode() and | ||
| branch = true | ||
| ) | ||
| ) | ||
| } |
There was a problem hiding this comment.
| private predicate uri_validator(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) { | |
| exists(DataFlow::CallCfgNode call, string funcs | | |
| funcs in ["in_domain", "in_azure_keyvault_domain", "in_azure_storage_domain"] | |
| | | |
| call = API::moduleImport("AntiSSRF").getMember("URIValidator").getMember(funcs).getACall() and | |
| call.getArg(0).asCfgNode() = node and | |
| ( | |
| // validator used in a comparison | |
| exists(CompareNode cn, Cmpop op, Node n | cn = g and n.getALocalSource() = call | | |
| ( | |
| // validator == true or validator == false or validator is True or validator is False | |
| (op instanceof Eq or op instanceof Is) and | |
| exists(ControlFlowNode l, boolean bool | | |
| l.getNode().(BooleanLiteral).booleanValue() = bool and | |
| bool in [true, false] and | |
| branch = bool and | |
| cn.operands(n.asCfgNode(), op, l) | |
| ) | |
| or | |
| // validator != false or validator != true or validator is not True or validator is not False | |
| (op instanceof NotEq or op instanceof IsNot) and | |
| exists(ControlFlowNode l, boolean bool | | |
| l.getNode().(BooleanLiteral).booleanValue() = bool and | |
| bool in [true, false] and | |
| branch = bool.booleanNot() and | |
| cn.operands(n.asCfgNode(), op, l) | |
| ) | |
| ) | |
| ) | |
| or | |
| // validator call directly (e.g., if URIValidator.in_domain(...) ) | |
| g = call.asCfgNode() and | |
| branch = true | |
| ) | |
| ) | |
| } | |
| private predicate uri_validator(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) { | |
| exists(DataFlow::CallCfgNode call, string funcs | | |
| funcs in ["in_domain", "in_azure_keyvault_domain", "in_azure_storage_domain"] and | |
| call = API::moduleImport("AntiSSRF").getMember("URIValidator").getMember(funcs).getACall() and | |
| call.getArg(0).asCfgNode() = node | |
| | | |
| // validator call directly (e.g., if URIValidator.in_domain(...) ) | |
| g = call.asCfgNode() and | |
| branch = true | |
| or | |
| // validator used in a comparison | |
| exists(Cmpop op, Node n, ControlFlowNode l | | |
| n.getALocalSource() = call and g.(CompareNode).operands(n.asCfgNode(), op, l) | |
| | | |
| // validator == true or validator == false or validator is True or validator is False | |
| (op instanceof Eq or op instanceof Is) and | |
| branch = l.getNode().(BooleanLiteral).booleanValue() | |
| or | |
| // validator != false or validator != true or validator is not True or validator is not False | |
| (op instanceof NotEq or op instanceof IsNot) and | |
| branch = l.getNode().(BooleanLiteral).booleanValue().booleanNot() | |
| ) | |
| ) | |
| } |
I think this should be equivalent, and hopefully a bit easier to read.
| --- | ||
| category: minorAnalysis | ||
| --- | ||
| * Modified SSRF tests to use postprocessing to more easily debug results. |
There was a problem hiding this comment.
I'm not sure this makes sense to put in the change notes, as it isn't really a user-facing change. I don't have strong feelings about it, however.
Uh oh!
There was an error while loading. Please reload this page.