mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
Merge pull request #7452 from jorgectf/python_jwt
Python: Add Python_JWT to JWT security query
This commit is contained in:
@@ -11,5 +11,6 @@ private import experimental.semmle.python.frameworks.NoSQL
|
||||
private import experimental.semmle.python.frameworks.Log
|
||||
private import experimental.semmle.python.frameworks.JWT
|
||||
private import experimental.semmle.python.libraries.PyJWT
|
||||
private import experimental.semmle.python.libraries.Python_JWT
|
||||
private import experimental.semmle.python.libraries.Authlib
|
||||
private import experimental.semmle.python.libraries.PythonJose
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
private import python
|
||||
private import experimental.semmle.python.Concepts
|
||||
private import semmle.python.ApiGraphs
|
||||
|
||||
private module Python_JWT {
|
||||
/**
|
||||
* Gets a call to `python_jwt.process_jwt`.
|
||||
*
|
||||
* Given the following example:
|
||||
*
|
||||
* ```py
|
||||
* python_jwt.process_jwt(token)
|
||||
* python_jwt.verify_jwt(token, "key", "HS256")
|
||||
* ```
|
||||
*
|
||||
* * `this` would be `jwt.process_jwt(token)`.
|
||||
* * `getPayload()`'s result would be `token`.
|
||||
* * `getKey()`'s result would be `"key"`.
|
||||
* * `getAlgorithm()`'s result would be `"HS256"`.
|
||||
* * `getAlgorithmstring()`'s result would be `HS256`.
|
||||
* * `getOptions()`'s result would be `none()`.
|
||||
* * `verifiesSignature()` predicate would succeed.
|
||||
*/
|
||||
private class PythonJwtProcessCall extends DataFlow::CallCfgNode, JWTDecoding::Range {
|
||||
PythonJwtProcessCall() {
|
||||
this = API::moduleImport("python_jwt").getMember("process_jwt").getACall()
|
||||
}
|
||||
|
||||
private DataFlow::CallCfgNode verifyCall() {
|
||||
result = API::moduleImport("python_jwt").getMember("verify_jwt").getACall() and
|
||||
this.getPayload().getALocalSource() = result.getArg(0).getALocalSource()
|
||||
}
|
||||
|
||||
override DataFlow::Node getPayload() { result = this.getArg(0) }
|
||||
|
||||
override DataFlow::Node getKey() { result = this.verifyCall().getArg(1) }
|
||||
|
||||
override DataFlow::Node getAlgorithm() { result = this.verifyCall().getArg(2) }
|
||||
|
||||
override string getAlgorithmString() {
|
||||
exists(StrConst str |
|
||||
DataFlow::exprNode(str).(DataFlow::LocalSourceNode).flowsTo(this.getAlgorithm()) and
|
||||
result = str.getText()
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getOptions() { none() }
|
||||
|
||||
override predicate verifiesSignature() { exists(this.verifyCall()) }
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
| pyjwt.py:22:12:22:16 | ControlFlowNode for token | is not verified with a cryptographic secret or public key. |
|
||||
| pyjwt.py:23:12:23:16 | ControlFlowNode for token | is not verified with a cryptographic secret or public key. |
|
||||
| python_jose.py:19:12:19:16 | ControlFlowNode for token | is not verified with a cryptographic secret or public key. |
|
||||
| python_jwt.py:14:28:14:32 | ControlFlowNode for token | is not verified with a cryptographic secret or public key. |
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import python_jwt
|
||||
|
||||
# GOOD
|
||||
|
||||
|
||||
def good(token):
|
||||
python_jwt.process_jwt(token)
|
||||
python_jwt.verify_jwt(token, "key", "HS256")
|
||||
|
||||
# BAD
|
||||
|
||||
|
||||
def bad(token):
|
||||
python_jwt.process_jwt(token)
|
||||
Reference in New Issue
Block a user