Skip to content

Commit 985cd1e

Browse files
committed
Python: Port py/request-without-cert-validation to use API graphs
1 parent 5958169 commit 985cd1e

File tree

3 files changed

+35
-16
lines changed

3 files changed

+35
-16
lines changed

python/ql/src/Security/CWE-295/RequestWithoutValidation.ql

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,37 @@
1111
*/
1212

1313
import python
14-
import semmle.python.web.Http
14+
private import semmle.python.dataflow.new.DataFlow
15+
private import semmle.python.Concepts
16+
private import semmle.python.ApiGraphs
1517

16-
FunctionValue requestFunction() { result = Module::named("requests").attr(httpVerbLower()) }
18+
/**
19+
* Gets a call to a method that makes an outgoing request using the `requests` module,
20+
* such as `requests.get` or `requests.put`, with the specified HTTP verb `verb`
21+
*/
22+
DataFlow::CallCfgNode outgoingRequestCall(string verb) {
23+
verb = HTTP::httpVerbLower() and
24+
result = API::moduleImport("requests").getMember(verb).getACall()
25+
}
26+
27+
/** Gets a reference to a falsey value (excluding None), with origin `origin`. */
28+
private DataFlow::TypeTrackingNode falseyNotNone(DataFlow::TypeTracker t, DataFlow::Node origin) {
29+
t.start() and
30+
result.asExpr().(ImmutableLiteral).booleanValue() = false and
31+
not result.asExpr() instanceof None and
32+
origin = result
33+
or
34+
exists(DataFlow::TypeTracker t2 | result = falseyNotNone(t2, origin).track(t2, t))
35+
}
1736

18-
/** requests treats None as the default and all other "falsey" values as False */
19-
predicate falseNotNone(Value v) { v.getDefiniteBooleanValue() = false and not v = Value::none_() }
37+
/** Gets a reference to a falsey value (excluding None), with origin `origin`. */
38+
DataFlow::Node falseyNotNone(DataFlow::Node origin) {
39+
falseyNotNone(DataFlow::TypeTracker::end(), origin).flowsTo(result)
40+
}
2041

21-
from CallNode call, FunctionValue func, Value falsey, ControlFlowNode origin
42+
from DataFlow::CallCfgNode call, DataFlow::Node falseyOrigin, string verb
2243
where
23-
func = requestFunction() and
24-
func.getACall() = call and
25-
falseNotNone(falsey) and
26-
call.getArgByName("verify").pointsTo(falsey, origin)
27-
select call, "Call to $@ with verify=$@", func, "requests." + func.getName(), origin, "False"
44+
call = outgoingRequestCall(verb) and
45+
// requests treats `None` as the default and all other "falsey" values as `False`.
46+
call.getArgByName("verify") = falseyNotNone(falseyOrigin)
47+
select call, "Call to requests." + verb + " with verify=$@", falseyOrigin, "False"
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
| make_request.py:5:1:5:48 | ControlFlowNode for Attribute() | Call to $@ with verify=$@ | ../lib/requests.py:2:1:2:36 | Function get | requests.get | make_request.py:5:43:5:47 | ControlFlowNode for False | False |
2-
| make_request.py:7:1:7:49 | ControlFlowNode for Attribute() | Call to $@ with verify=$@ | ../lib/requests.py:11:1:11:46 | Function post | requests.post | make_request.py:7:44:7:48 | ControlFlowNode for False | False |
3-
| make_request.py:12:1:12:39 | ControlFlowNode for put() | Call to $@ with verify=$@ | ../lib/requests.py:14:1:14:34 | Function put | requests.put | make_request.py:12:34:12:38 | ControlFlowNode for False | False |
4-
| make_request.py:28:5:28:46 | ControlFlowNode for patch() | Call to $@ with verify=$@ | ../lib/requests.py:17:1:17:36 | Function patch | requests.patch | make_request.py:30:6:30:10 | ControlFlowNode for False | False |
5-
| make_request.py:34:1:34:45 | ControlFlowNode for Attribute() | Call to $@ with verify=$@ | ../lib/requests.py:11:1:11:46 | Function post | requests.post | make_request.py:34:44:34:44 | ControlFlowNode for IntegerLiteral | False |
1+
| make_request.py:5:1:5:48 | ControlFlowNode for Attribute() | Call to requests.get with verify=$@ | make_request.py:5:43:5:47 | ControlFlowNode for False | False |
2+
| make_request.py:7:1:7:49 | ControlFlowNode for Attribute() | Call to requests.post with verify=$@ | make_request.py:7:44:7:48 | ControlFlowNode for False | False |
3+
| make_request.py:12:1:12:39 | ControlFlowNode for put() | Call to requests.put with verify=$@ | make_request.py:12:34:12:38 | ControlFlowNode for False | False |
4+
| make_request.py:28:5:28:46 | ControlFlowNode for patch() | Call to requests.patch with verify=$@ | make_request.py:30:6:30:10 | ControlFlowNode for False | False |
5+
| make_request.py:34:1:34:45 | ControlFlowNode for Attribute() | Call to requests.post with verify=$@ | make_request.py:34:44:34:44 | ControlFlowNode for IntegerLiteral | False |

python/ql/test/query-tests/Security/CWE-295-RequestWithoutValidation/options

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)