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

Skip to content

Commit f82ed85

Browse files
committed
Model python_jwt.process_jwt
1 parent 8fabbd6 commit f82ed85

4 files changed

Lines changed: 72 additions & 0 deletions

File tree

python/ql/src/experimental/semmle/python/Frameworks.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ private import experimental.semmle.python.frameworks.NoSQL
1111
private import experimental.semmle.python.frameworks.Log
1212
private import experimental.semmle.python.frameworks.JWT
1313
private import experimental.semmle.python.libraries.PyJWT
14+
private import experimental.semmle.python.libraries.Python_JWT
1415
private import experimental.semmle.python.libraries.Authlib
1516
private import experimental.semmle.python.libraries.PythonJose
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
private import python
2+
private import experimental.semmle.python.Concepts
3+
private import semmle.python.ApiGraphs
4+
5+
private module Python_JWT {
6+
/**
7+
* Gets a call to `python_jwt.process_jwt`.
8+
*
9+
* Given the following example:
10+
*
11+
* ```py
12+
* python_jwt.process_jwt(token)
13+
* python_jwt.verify_jwt(token, "key", "HS256")
14+
* ```
15+
*
16+
* * `this` would be `jwt.process_jwt(token)`.
17+
* * `getPayload()`'s result would be `token`.
18+
* * `getKey()`'s result would be `"key"`.
19+
* * `getAlgorithm()`'s result would be `"HS256"`.
20+
* * `getAlgorithmstring()`'s result would be `HS256`.
21+
* * `getOptions()`'s result would be `none()`.
22+
* * `verifiesSignature()` predicate would succeed.
23+
*/
24+
private class Python_JWTProcessCall extends DataFlow::CallCfgNode, JWTDecoding::Range {
25+
DataFlow::CallCfgNode verifyCall;
26+
boolean verifiesSignature;
27+
28+
Python_JWTProcessCall() {
29+
this = API::moduleImport("python_jwt").getMember("process_jwt").getACall() and
30+
(
31+
verifyCall = API::moduleImport("python_jwt").getMember("verify_jwt").getACall() and
32+
this.getArg(0).getALocalSource().flowsTo(verifyCall.getArg(0)) and
33+
verifiesSignature = true
34+
or
35+
verifiesSignature = false
36+
)
37+
}
38+
39+
override DataFlow::Node getPayload() { result = this.getArg(0) }
40+
41+
override DataFlow::Node getKey() { result = verifyCall.getArg(1) }
42+
43+
override DataFlow::Node getAlgorithm() { result = verifyCall.getArg(2) }
44+
45+
override string getAlgorithmString() {
46+
exists(StrConst str |
47+
DataFlow::exprNode(str).(DataFlow::LocalSourceNode).flowsTo(this.getAlgorithm()) and
48+
result = str.getText()
49+
)
50+
}
51+
52+
override DataFlow::Node getOptions() { none() }
53+
54+
override predicate verifiesSignature() { exists( | verifiesSignature = true) }
55+
}
56+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
| pyjwt.py:22:12:22:16 | ControlFlowNode for token | is not verified with a cryptographic secret or public key. |
22
| pyjwt.py:23:12:23:16 | ControlFlowNode for token | is not verified with a cryptographic secret or public key. |
33
| python_jose.py:19:12:19:16 | ControlFlowNode for token | is not verified with a cryptographic secret or public key. |
4+
| python_jwt.py:14:24:14:29 | ControlFlowNode for token3 | is not verified with a cryptographic secret or public key. |
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import python_jwt
2+
3+
# GOOD
4+
5+
token1 = "1"
6+
python_jwt.process_jwt(token1)
7+
python_jwt.verify_jwt(token1, "key", "HS256")
8+
9+
# BAD
10+
11+
# no call to verify_jwt
12+
13+
token3 = "123"
14+
python_jwt.process_jwt(token3)

0 commit comments

Comments
 (0)