Polish documentation

This commit is contained in:
jorgectf
2021-10-28 13:09:28 +02:00
parent 350cbb4c5d
commit 7069f45864
5 changed files with 104 additions and 9 deletions

View File

@@ -4,11 +4,11 @@
<qhelp>
<overview>
<p>Applications encoding a JSON Web Token (JWT) may be vulnerable when the applied key or algorithm
is empty or None.</p>
is empty or <code>None</code>.</p>
</overview>
<recommendation>
<p>Use non-empty nor None values while encoding JWT payloads.</p>
<p>Use non-empty nor <code>None</code> values while encoding JWT payloads.</p>
</recommendation>
<example>

View File

@@ -1,8 +1,10 @@
private import python
private import semmle.python.ApiGraphs
/** Checks if the argument is empty or none. */
predicate isEmptyOrNone(DataFlow::Node arg) { isEmpty(arg) or isNone(arg) }
/** Checks if an empty string `""` flows to `arg` */
predicate isEmpty(DataFlow::Node arg) {
exists(StrConst emptyString |
emptyString.getText() = "" and
@@ -10,11 +12,12 @@ predicate isEmpty(DataFlow::Node arg) {
)
}
/** Checks if `None` flows to `arg` */
predicate isNone(DataFlow::Node arg) {
exists( | DataFlow::exprNode(any(None no)).(DataFlow::LocalSourceNode).flowsTo(arg))
}
/** Checks if `False` flows to `arg` */
predicate isFalse(DataFlow::Node arg) {
exists( | DataFlow::exprNode(any(False falseExpr)).(DataFlow::LocalSourceNode).flowsTo(arg))
}

View File

@@ -18,8 +18,23 @@ private module Authlib {
/** Gets a reference to `jwt.decode` */
private API::Node authlibJWTDecode() { result = authlibJWT().getMember("decode") }
// def encode(self, header, payload, key, check=True):
/**
* Gets a call to `authlib.jose.(jwt|JsonWebToken).encode`.
*
* Given the following example:
*
* ```py
* jwt.encode({"alg": "HS256"}, token, "key")
* ```
*
* * `this` would be `jwt.encode({"alg": "HS256"}, token, "key")`.
* * `getPayload()`'s result would be `token`.
* * `getKey()`'s result would be `"key"`.
* * `getAlgorithm()`'s result would be `"HS256"`.
* * `getAlgorithmstring()`'s result would be `HS256`.
*/
private class AuthlibJWTEncodeCall extends DataFlow::CallCfgNode, JWTEncoding::Range {
// def encode(self, header, payload, key, check=True):
AuthlibJWTEncodeCall() { this = authlibJWTEncode().getACall() }
override DataFlow::Node getPayload() { result = this.getArg(1) }
@@ -42,8 +57,21 @@ private module Authlib {
}
}
// def decode(self, s, key, claims_cls=None, claims_options=None, claims_params=None):
/**
* Gets a call to `authlib.jose.(jwt|JsonWebToken).decode`
*
* Given the following example:
*
* ```py
* jwt.decode(token, key)
* ```
*
* * `this` would be `jwt.decode(token, key)`.
* * `getPayload()`'s result would be `token`.
* * `getKey()`'s result would be `key`.
*/
private class AuthlibJWTDecodeCall extends DataFlow::CallCfgNode, JWTDecoding::Range {
// def decode(self, s, key, claims_cls=None, claims_options=None, claims_params=None):
AuthlibJWTDecodeCall() { this = authlibJWTDecode().getACall() }
override DataFlow::Node getPayload() { result = this.getArg(0) }

View File

@@ -10,8 +10,23 @@ private module PyJWT {
/** Gets a reference to `jwt.decode` */
private API::Node pyjwtDecode() { result = API::moduleImport("jwt").getMember("decode") }
// def encode(self, payload, key, algorithm="HS256", headers=None, json_encoder=None)
/**
* Gets a call to `jwt.encode`.
*
* Given the following example:
*
* ```py
* jwt.encode(token, "key", "HS256")
* ```
*
* * `this` would be `jwt.encode(token, "key", "HS256")`.
* * `getPayload()`'s result would be `token`.
* * `getKey()`'s result would be `"key"`.
* * `getAlgorithm()`'s result would be `"HS256"`.
* * `getAlgorithmstring()`'s result would be `HS256`.
*/
private class PyJWTEncodeCall extends DataFlow::CallCfgNode, JWTEncoding::Range {
// def encode(self, payload, key, algorithm="HS256", headers=None, json_encoder=None)
PyJWTEncodeCall() { this = pyjwtEncode().getACall() }
override DataFlow::Node getPayload() {
@@ -32,8 +47,25 @@ private module PyJWT {
}
}
// def decode(self, jwt, key="", algorithms=None, options=None)
/**
* Gets a call to `jwt.decode`.
*
* Given the following example:
*
* ```py
* jwt.decode(token, key, "HS256", options={"verify_signature": True})
* ```
*
* * `this` would be `jwt.decode(token, key, options={"verify_signature": True})`.
* * `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 `{"verify_signature": True}`.
* * `verifiesSignature()` predicate would succeed.
*/
private class PyJWTDecodeCall extends DataFlow::CallCfgNode, JWTDecoding::Range {
// def decode(self, jwt, key="", algorithms=None, options=None)
PyJWTDecodeCall() { this = pyjwtDecode().getACall() }
override DataFlow::Node getPayload() { result in [this.getArg(0), this.getArgByName("jwt")] }

View File

@@ -13,8 +13,23 @@ private module PythonJose {
/** Gets a reference to `jwt.decode` */
private API::Node joseJWTDecode() { result = joseJWT().getMember("decode") }
// def encode(claims, key, algorithm=ALGORITHMS.HS256, headers=None, access_token=None):
/**
* Gets a call to `jwt.encode`.
*
* Given the following example:
*
* ```py
* jwt.encode(token, key="key", algorithm="HS256")
* ```
*
* * `this` would be `jwt.encode(token, key="key", algorithm="HS256")`.
* * `getPayload()`'s result would be `token`.
* * `getKey()`'s result would be `"key"`.
* * `getAlgorithm()`'s result would be `"HS256"`.
* * `getAlgorithmstring()`'s result would be `HS256`.
*/
private class JoseJWTEncodeCall extends DataFlow::CallCfgNode, JWTEncoding::Range {
// def encode(claims, key, algorithm=ALGORITHMS.HS256, headers=None, access_token=None):
JoseJWTEncodeCall() { this = joseJWTEncode().getACall() }
override DataFlow::Node getPayload() { result = this.getArg(0) }
@@ -33,8 +48,25 @@ private module PythonJose {
}
}
// def decode(token, key, algorithms=None, options=None, audience=None, issuer=None, subject=None, access_token=None):
/**
* Gets a call to `jwt.decode`.
*
* Given the following example:
*
* ```py
* jwt.decode(token, "key", "HS256")
* ```
*
* * `this` would be `jwt.decode(token, "key", "HS256")`.
* * `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 JoseJWTDecodeCall extends DataFlow::CallCfgNode, JWTDecoding::Range {
// def decode(token, key, algorithms=None, options=None, audience=None, issuer=None, subject=None, access_token=None):
JoseJWTDecodeCall() { this = joseJWTDecode().getACall() }
override DataFlow::Node getPayload() { result = this.getArg(0) }