diff --git a/rules/python/security/python-pyjwt-hardcoded-secret-python.yml b/rules/python/security/python-pyjwt-hardcoded-secret-python.yml new file mode 100644 index 00000000..046c3fad --- /dev/null +++ b/rules/python/security/python-pyjwt-hardcoded-secret-python.yml @@ -0,0 +1,441 @@ +id: python-pyjwt-hardcoded-secret-python +language: python +severity: warning +message: >- + A secret is hard-coded in the application. Secrets stored in source + code, such as credentials, identifiers, and other types of sensitive data, + can be leaked and used by internal or external malicious actors. Use + environment variables to securely provide credentials and other secrets or + retrieve them from a secure vault or Hardware Security Module (HSM). +note: >- + [CWE-798]: Use of Hard-coded Credentials + [OWASP A01:2021]: Identification and Authentication Failures + [REFERENCES] + https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +utils: + match_call: + kind: call + all: + - has: + stopBy: end + kind: attribute + field: function + all: + - has: + stopBy: end + kind: identifier + field: object + regex: "^jwt$" + - has: + stopBy: end + kind: identifier + field: attribute + regex: ^(encode|decode)$ + - has: + stopBy: end + kind: argument_list + field: arguments + all: + - has: + stopBy: end + kind: dictionary + has: + stopBy: end + kind: pair + all: + - has: + stopBy: end + kind: string + field: key + - has: + stopBy: end + kind: string + field: value + - has: + stopBy: end + kind: identifier + pattern: $R + - has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: end + kind: identifier + field: name + - has: + stopBy: end + kind: string + field: value + all: + - has: + stopBy: end + kind: string_start + - has: + stopBy: end + kind: string_content + - has: + stopBy: end + kind: string_end + inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: expression_statement + all: + - has: + stopBy: end + kind: assignment + has: + stopBy: end + kind: identifier + pattern: $R + - has: + stopBy: end + kind: string + all: + - has: + stopBy: end + kind: string_start + - has: + stopBy: end + kind: string_content + - has: + stopBy: end + kind: string_end + match_call_with_string: + kind: call + all: + - has: + stopBy: end + kind: attribute + field: function + all: + - has: + stopBy: end + kind: identifier + field: object + regex: "^jwt$" + - has: + stopBy: end + kind: identifier + field: attribute + regex: ^(encode|decode)$ + - has: + stopBy: end + kind: argument_list + field: arguments + all: + - has: + stopBy: end + kind: dictionary + has: + stopBy: end + kind: pair + all: + - has: + stopBy: end + kind: string + field: key + - has: + stopBy: end + kind: string + field: value + - has: + kind: string + all: + - has: + stopBy: end + kind: string_start + - has: + stopBy: end + kind: string_content + - has: + stopBy: end + kind: string_end + - has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: end + kind: identifier + field: name + - has: + stopBy: end + kind: string + field: value + all: + - has: + stopBy: end + kind: string_start + - has: + stopBy: end + kind: string_content + - has: + stopBy: end + kind: string_end + inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: expression_statement + all: + - has: + stopBy: end + kind: assignment + has: + stopBy: end + kind: identifier + - has: + stopBy: end + kind: string + all: + - has: + stopBy: end + kind: string_start + - has: + stopBy: end + kind: string_content + - has: + stopBy: end + kind: string_end + match_from_imports: + kind: call + all: + - has: + stopBy: end + kind: attribute + field: function + all: + - has: + stopBy: end + kind: identifier + field: object + pattern: $T + - has: + stopBy: end + kind: identifier + field: attribute + regex: ^(encode|decode)$ + - has: + stopBy: end + kind: argument_list + field: arguments + all: + - has: + stopBy: end + kind: dictionary + has: + stopBy: end + kind: pair + all: + - has: + stopBy: end + kind: string + field: key + - has: + stopBy: end + kind: string + field: value + - has: + stopBy: end + kind: string + all: + - has: + stopBy: end + kind: string_start + - has: + stopBy: end + kind: string_content + - has: + stopBy: end + kind: string_end + - has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: end + kind: identifier + field: name + - has: + stopBy: end + kind: string + field: value + all: + - has: + stopBy: end + kind: string_start + - has: + stopBy: end + kind: string_content + - has: + stopBy: end + kind: string_end + inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: import_statement + has: + stopBy: end + kind: aliased_import + field: name + all: + - has: + stopBy: end + kind: dotted_name + field: name + has: + stopBy: end + kind: identifier + regex: "^jwt$" + - has: + stopBy: end + kind: identifier + field: alias + pattern: $T + match_without_follow_import: + kind: call + all: + - has: + stopBy: end + kind: attribute + field: function + all: + - has: + stopBy: end + kind: identifier + field: object + regex: "^jwt$" + - has: + stopBy: end + kind: identifier + field: attribute + regex: ^(encode|decode)$ + - has: + stopBy: end + kind: argument_list + field: arguments + all: + - has: + stopBy: end + kind: dictionary + has: + stopBy: end + kind: pair + all: + - has: + stopBy: end + kind: string + field: key + - has: + stopBy: end + kind: string + field: value + - has: + kind: string + all: + - has: + stopBy: end + kind: string_start + - has: + stopBy: end + kind: string_content + - has: + stopBy: end + kind: string_end + - has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: end + kind: identifier + field: name + - has: + stopBy: end + kind: string + field: value + all: + - has: + stopBy: end + kind: string_start + - has: + stopBy: end + kind: string_content + - has: + stopBy: end + kind: string_end + inside: + stopBy: end + kind: expression_statement + + match_without_follow_import_string: + kind: call + all: + - has: + stopBy: end + kind: attribute + field: function + all: + - has: + stopBy: end + kind: identifier + field: object + regex: "^jwt$" + - has: + stopBy: end + kind: identifier + field: attribute + regex: ^(encode|decode)$ + - has: + stopBy: end + kind: argument_list + field: arguments + all: + - has: + stopBy: end + kind: string + - has: + stopBy: end + kind: string + - has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: end + kind: identifier + field: name + - has: + stopBy: end + kind: list + field: value + has: + stopBy: end + kind: string + all: + - has: + stopBy: end + kind: string_start + - has: + stopBy: end + kind: string_content + - has: + stopBy: end + kind: string_end + inside: + stopBy: end + kind: expression_statement +rule: + any: + - matches: match_call + - matches: match_call_with_string + - matches: match_from_imports + - matches: match_without_follow_import + - matches: match_without_follow_import_string diff --git a/rules/python/security/python-redis-hardcoded-secret-python.yml b/rules/python/security/python-redis-hardcoded-secret-python.yml new file mode 100644 index 00000000..ec069313 --- /dev/null +++ b/rules/python/security/python-redis-hardcoded-secret-python.yml @@ -0,0 +1,168 @@ +id: python-redis-hardcoded-secret-python +severity: warning +language: python +message: >- + A secret is hard-coded in the application. Secrets stored in source + code, such as credentials, identifiers, and other types of sensitive data, + can be leaked and used by internal or external malicious actors. Use + environment variables to securely provide credentials and other secrets or + retrieve them from a secure vault or Hardware Security Module (HSM). +note: >- + [CWE-798] Use of Hard-coded Credentials. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +utils: + redis.Redis(..., password="...",...): + kind: call + all: + - has: + stopBy: neighbor + kind: attribute + pattern: redis.Redis + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^password$ + - has: + stopBy: neighbor + kind: string + has: + stopBy: end + kind: string_content + redis.Redis(..., password="...",...)_with_instance: + kind: call + all: + - has: + stopBy: neighbor + kind: attribute + pattern: redis.Redis + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^password$ + - has: + stopBy: neighbor + kind: identifier + pattern: $P + - inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: assignment + all: + - has: + stopBy: end + kind: identifier + paatern: $P + - has: + stopBy: neighbor + kind: string + has: + stopby: end + kind: string_content + Redis(..., password="...",...): + kind: call + all: + - has: + stopBy: neighbor + kind: identifier + pattern: Redis + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^password$ + - has: + stopBy: neighbor + kind: string + has: + stopBy: end + kind: string_content + - inside: + stopBy: end + kind: module + has: + stopBy: end + kind: import_from_statement + pattern: from redis import Redis + Redis(..., password="...",...)_with_instance: + kind: call + all: + - has: + stopBy: neighbor + kind: identifier + pattern: Redis + - has: + stopBy: neighbor + kind: argument_list + has: + stopBy: end + kind: keyword_argument + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^password$ + - has: + stopBy: neighbor + kind: identifier + pattern: $S + nthChild: 2 + - inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: assignment + all: + - has: + stopBy: end + kind: identifier + pattern: $S + - has: + stopBy: neighbor + kind: string + has: + stopby: end + kind: string_content + - inside: + stopBy: end + kind: module + has: + stopBy: end + kind: import_from_statement + pattern: from redis import Redis +rule: + kind: call + any: + - matches: redis.Redis(..., password="...",...) + - matches: redis.Redis(..., password="...",...)_with_instance + - matches: Redis(..., password="...",...) + - matches: Redis(..., password="...",...)_with_instance diff --git a/rules/python/security/python-requests-empty-password-python.yml b/rules/python/security/python-requests-empty-password-python.yml new file mode 100644 index 00000000..32f0a263 --- /dev/null +++ b/rules/python/security/python-requests-empty-password-python.yml @@ -0,0 +1,338 @@ +id: python-requests-empty-password-python +severity: warning +language: python +message: >- + The application creates a database connection with an empty password. + This can lead to unauthorized access by either an internal or external + malicious actor. To prevent this vulnerability, enforce authentication + when connecting to a database by using environment variables to securely + provide credentials or retrieving them from a secure vault or HSM + (Hardware Security Module). +note: >- + [CWE-287] Improper Authentication. + [REFERENCES] + - https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html +utils: + requests.auth.HTTPBasicAuth($USER,"",...): + kind: call + all: + - has: + stopBy: neighbor + kind: attribute + regex: ^requests.auth.HTTPBasicAuth|requests.auth.HTTPDigestAuth|requests.auth.HTTPProxyAuth$ + - has: + stopBy: neighbor + kind: argument_list + all: + - has: + stopBy: neighbor + pattern: $$$ + nthChild: 1 + - has: + stopBy: neighbor + kind: string + nthChild: 2 + not: + has: + stopBy: end + kind: string_content + HTTPBasicAuth($USER,"",...): + kind: call + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^HTTPBasicAuth$ + - has: + stopBy: neighbor + kind: argument_list + all: + - has: + stopBy: neighbor + kind: string + nthChild: 1 + has: + stopBy: end + kind: string_content + - has: + stopBy: neighbor + kind: string + nthChild: 2 + not: + has: + stopBy: end + kind: string_content + - inside: + stopBy: end + kind: module + has: + stopBy: end + kind: import_from_statement + pattern: from requests.auth import HTTPBasicAuth + HTTPDigestAuth($USER,"",...): + kind: call + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^HTTPDigestAuth$ + - has: + stopBy: neighbor + kind: argument_list + all: + - has: + stopBy: neighbor + kind: string + nthChild: 1 + has: + stopBy: end + kind: string_content + - has: + stopBy: neighbor + kind: string + nthChild: 2 + not: + has: + stopBy: end + kind: string_content + - inside: + stopBy: end + kind: module + has: + stopBy: end + kind: import_from_statement + pattern: from requests.auth import HTTPDigestAuth + HTTPProxyAuth($USER,"",...): + kind: call + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^HTTPProxyAuth$ + - has: + stopBy: neighbor + kind: argument_list + all: + - has: + stopBy: neighbor + kind: string + nthChild: 1 + has: + stopBy: end + kind: string_content + - has: + stopBy: neighbor + kind: string + nthChild: 2 + not: + has: + stopBy: end + kind: string_content + - inside: + stopBy: end + kind: module + has: + stopBy: end + kind: import_from_statement + pattern: from requests.auth import HTTPProxyAuth + requests.auth.HTTPBasicAuth($USER,"",...)with_instance: + kind: call + all: + - has: + stopBy: neighbor + kind: attribute + regex: ^requests.auth.HTTPBasicAuth|requests.auth.HTTPDigestAuth|requests.auth.HTTPProxyAuth$ + - has: + stopBy: neighbor + kind: argument_list + all: + - has: + stopBy: neighbor + pattern: $$$ + nthChild: 1 + - has: + stopBy: neighbor + kind: identifier + pattern: $H + - inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: assignment + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $H + - has: + stopBy: neighbor + kind: string + not: + has: + stopBy: end + kind: string_content + HTTPBasicAuth($USER,"",...)with_instance: + kind: call + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^HTTPBasicAuth$ + - has: + stopBy: neighbor + kind: argument_list + all: + - has: + stopBy: neighbor + kind: string + nthChild: 1 + has: + stopBy: end + kind: string_content + - has: + stopBy: neighbor + kind: identifier + pattern: $H + - inside: + stopBy: end + kind: module + has: + stopBy: end + kind: import_from_statement + pattern: from requests.auth import HTTPBasicAuth + - inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: assignment + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $H + - has: + stopBy: neighbor + kind: string + not: + has: + stopBy: end + kind: string_content + HTTPDigestAuth($USER,"",...)with_instance: + kind: call + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^HTTPDigestAuth$ + - has: + stopBy: neighbor + kind: argument_list + all: + - has: + stopBy: neighbor + kind: string + nthChild: 1 + has: + stopBy: end + kind: string_content + - has: + stopBy: neighbor + kind: identifier + pattern: $H + - inside: + stopBy: end + kind: module + has: + stopBy: end + kind: import_from_statement + pattern: from requests.auth import HTTPDigestAuth + - inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: assignment + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $H + - has: + stopBy: neighbor + kind: string + not: + has: + stopBy: end + kind: string_content + HTTPProxyAuth($USER,"",...)with_instance: + kind: call + all: + - has: + stopBy: neighbor + kind: identifier + regex: ^HTTPProxyAuth$ + - has: + stopBy: neighbor + kind: argument_list + all: + - has: + stopBy: neighbor + kind: string + nthChild: 1 + has: + stopBy: end + kind: string_content + - has: + stopBy: neighbor + kind: identifier + pattern: $H + - inside: + stopBy: end + kind: module + has: + stopBy: end + kind: import_from_statement + pattern: from requests.auth import HTTPProxyAuth + - inside: + stopBy: end + kind: expression_statement + follows: + stopBy: end + kind: expression_statement + has: + stopBy: neighbor + kind: assignment + all: + - has: + stopBy: neighbor + kind: identifier + pattern: $H + - has: + stopBy: neighbor + kind: string + not: + has: + stopBy: end + kind: string_content +rule: + kind: call + any: + - matches: requests.auth.HTTPBasicAuth($USER,"",...) + - matches: HTTPBasicAuth($USER,"",...) + - matches: HTTPDigestAuth($USER,"",...) + - matches: HTTPProxyAuth($USER,"",...) + - matches: requests.auth.HTTPBasicAuth($USER,"",...)with_instance + - matches: HTTPBasicAuth($USER,"",...)with_instance + - matches: HTTPDigestAuth($USER,"",...)with_instance + - matches: HTTPProxyAuth($USER,"",...)with_instance diff --git a/tests/__snapshots__/python-pyjwt-hardcoded-secret-python-snapshot.yml b/tests/__snapshots__/python-pyjwt-hardcoded-secret-python-snapshot.yml new file mode 100644 index 00000000..9e164c4d --- /dev/null +++ b/tests/__snapshots__/python-pyjwt-hardcoded-secret-python-snapshot.yml @@ -0,0 +1,327 @@ +id: python-pyjwt-hardcoded-secret-python +snapshots: + ? | + import os + import jwt + import jwt as lsadlsaldsa + key = "secret" + jwt.encode({"some": "payload"}, "123", algorithm="HS256") + : labels: + - source: 'jwt.encode({"some": "payload"}, "123", algorithm="HS256")' + style: primary + start: 62 + end: 119 + - source: jwt + style: secondary + start: 62 + end: 65 + - source: encode + style: secondary + start: 66 + end: 72 + - source: jwt.encode + style: secondary + start: 62 + end: 72 + - source: '"some"' + style: secondary + start: 74 + end: 80 + - source: '"payload"' + style: secondary + start: 82 + end: 91 + - source: '"some": "payload"' + style: secondary + start: 74 + end: 91 + - source: '{"some": "payload"}' + style: secondary + start: 73 + end: 92 + - source: '"' + style: secondary + start: 94 + end: 95 + - source: '123' + style: secondary + start: 95 + end: 98 + - source: '"' + style: secondary + start: 98 + end: 99 + - source: '"123"' + style: secondary + start: 94 + end: 99 + - source: algorithm + style: secondary + start: 101 + end: 110 + - source: '"' + style: secondary + start: 111 + end: 112 + - source: HS256 + style: secondary + start: 112 + end: 117 + - source: '"' + style: secondary + start: 117 + end: 118 + - source: '"HS256"' + style: secondary + start: 111 + end: 118 + - source: algorithm="HS256" + style: secondary + start: 101 + end: 118 + - source: '({"some": "payload"}, "123", algorithm="HS256")' + style: secondary + start: 72 + end: 119 + - source: key + style: secondary + start: 47 + end: 50 + - source: key = "secret" + style: secondary + start: 47 + end: 61 + - source: '"' + style: secondary + start: 53 + end: 54 + - source: secret + style: secondary + start: 54 + end: 60 + - source: '"' + style: secondary + start: 60 + end: 61 + - source: '"secret"' + style: secondary + start: 53 + end: 61 + - source: key = "secret" + style: secondary + start: 47 + end: 61 + - source: 'jwt.encode({"some": "payload"}, "123", algorithm="HS256")' + style: secondary + start: 62 + end: 119 + ? | + import os + import jwt + import jwt as lsadlsaldsa + key = "secret" + jwt.encode({"some": "payload"}, key, algorithm="HS256") + : labels: + - source: 'jwt.encode({"some": "payload"}, key, algorithm="HS256")' + style: primary + start: 62 + end: 117 + - source: jwt + style: secondary + start: 62 + end: 65 + - source: encode + style: secondary + start: 66 + end: 72 + - source: jwt.encode + style: secondary + start: 62 + end: 72 + - source: '"some"' + style: secondary + start: 74 + end: 80 + - source: '"payload"' + style: secondary + start: 82 + end: 91 + - source: '"some": "payload"' + style: secondary + start: 74 + end: 91 + - source: '{"some": "payload"}' + style: secondary + start: 73 + end: 92 + - source: key + style: secondary + start: 94 + end: 97 + - source: algorithm + style: secondary + start: 99 + end: 108 + - source: '"' + style: secondary + start: 109 + end: 110 + - source: HS256 + style: secondary + start: 110 + end: 115 + - source: '"' + style: secondary + start: 115 + end: 116 + - source: '"HS256"' + style: secondary + start: 109 + end: 116 + - source: algorithm="HS256" + style: secondary + start: 99 + end: 116 + - source: '({"some": "payload"}, key, algorithm="HS256")' + style: secondary + start: 72 + end: 117 + - source: key + style: secondary + start: 47 + end: 50 + - source: key = "secret" + style: secondary + start: 47 + end: 61 + - source: '"' + style: secondary + start: 53 + end: 54 + - source: secret + style: secondary + start: 54 + end: 60 + - source: '"' + style: secondary + start: 60 + end: 61 + - source: '"secret"' + style: secondary + start: 53 + end: 61 + - source: key = "secret" + style: secondary + start: 47 + end: 61 + - source: 'jwt.encode({"some": "payload"}, key, algorithm="HS256")' + style: secondary + start: 62 + end: 117 + ? | + import os + import jwt + import jwt as lsadlsaldsa + key = "secret" + lsadlsaldsa.encode({"some": "payload"}, "123", algorithm="HS256") + : labels: + - source: 'lsadlsaldsa.encode({"some": "payload"}, "123", algorithm="HS256")' + style: primary + start: 62 + end: 127 + - source: lsadlsaldsa + style: secondary + start: 62 + end: 73 + - source: encode + style: secondary + start: 74 + end: 80 + - source: lsadlsaldsa.encode + style: secondary + start: 62 + end: 80 + - source: '"some"' + style: secondary + start: 82 + end: 88 + - source: '"payload"' + style: secondary + start: 90 + end: 99 + - source: '"some": "payload"' + style: secondary + start: 82 + end: 99 + - source: '{"some": "payload"}' + style: secondary + start: 81 + end: 100 + - source: '"' + style: secondary + start: 82 + end: 83 + - source: some + style: secondary + start: 83 + end: 87 + - source: '"' + style: secondary + start: 87 + end: 88 + - source: '"some"' + style: secondary + start: 82 + end: 88 + - source: algorithm + style: secondary + start: 109 + end: 118 + - source: '"' + style: secondary + start: 119 + end: 120 + - source: HS256 + style: secondary + start: 120 + end: 125 + - source: '"' + style: secondary + start: 125 + end: 126 + - source: '"HS256"' + style: secondary + start: 119 + end: 126 + - source: algorithm="HS256" + style: secondary + start: 109 + end: 126 + - source: '({"some": "payload"}, "123", algorithm="HS256")' + style: secondary + start: 80 + end: 127 + - source: jwt + style: secondary + start: 28 + end: 31 + - source: jwt + style: secondary + start: 28 + end: 31 + - source: lsadlsaldsa + style: secondary + start: 35 + end: 46 + - source: jwt as lsadlsaldsa + style: secondary + start: 28 + end: 46 + - source: import jwt as lsadlsaldsa + style: secondary + start: 21 + end: 46 + - source: 'lsadlsaldsa.encode({"some": "payload"}, "123", algorithm="HS256")' + style: secondary + start: 62 + end: 127 diff --git a/tests/__snapshots__/python-redis-hardcoded-secret-python-snapshot.yml b/tests/__snapshots__/python-redis-hardcoded-secret-python-snapshot.yml new file mode 100644 index 00000000..0fa639bc --- /dev/null +++ b/tests/__snapshots__/python-redis-hardcoded-secret-python-snapshot.yml @@ -0,0 +1,261 @@ +id: python-redis-hardcoded-secret-python +snapshots: + ? | + foobar = 'password' + redis_client = redis.Redis(host='1.2.3.4', password=foobar, port=6379) + : labels: + - source: redis.Redis(host='1.2.3.4', password=foobar, port=6379) + style: primary + start: 35 + end: 90 + - source: redis.Redis + style: secondary + start: 35 + end: 46 + - source: password + style: secondary + start: 63 + end: 71 + - source: password + style: secondary + start: 63 + end: 71 + - source: password=foobar + style: secondary + start: 63 + end: 78 + - source: (host='1.2.3.4', password=foobar, port=6379) + style: secondary + start: 46 + end: 90 + - source: foobar + style: secondary + start: 0 + end: 6 + - source: password + style: secondary + start: 10 + end: 18 + - source: '''password''' + style: secondary + start: 9 + end: 19 + - source: foobar = 'password' + style: secondary + start: 0 + end: 19 + - source: foobar = 'password' + style: secondary + start: 0 + end: 19 + - source: redis_client = redis.Redis(host='1.2.3.4', password=foobar, port=6379) + style: secondary + start: 20 + end: 90 + ? | + from redis import Redis + foobar = 'password' + redis_client = Redis(host='1.2.3.4', password=foobar, port=6379) + : labels: + - source: Redis(host='1.2.3.4', password=foobar, port=6379) + style: primary + start: 59 + end: 108 + - source: Redis + style: secondary + start: 59 + end: 64 + - source: password + style: secondary + start: 81 + end: 89 + - source: foobar + style: secondary + start: 90 + end: 96 + - source: password=foobar + style: secondary + start: 81 + end: 96 + - source: (host='1.2.3.4', password=foobar, port=6379) + style: secondary + start: 64 + end: 108 + - source: foobar + style: secondary + start: 24 + end: 30 + - source: password + style: secondary + start: 34 + end: 42 + - source: '''password''' + style: secondary + start: 33 + end: 43 + - source: foobar = 'password' + style: secondary + start: 24 + end: 43 + - source: foobar = 'password' + style: secondary + start: 24 + end: 43 + - source: redis_client = Redis(host='1.2.3.4', password=foobar, port=6379) + style: secondary + start: 44 + end: 108 + - source: from redis import Redis + style: secondary + start: 0 + end: 23 + - source: | + from redis import Redis + foobar = 'password' + redis_client = Redis(host='1.2.3.4', password=foobar, port=6379) + style: secondary + start: 0 + end: 109 + ? | + from redis import Redis + redis_client = Redis( + host='prod.redis.example.com', + port=6379, + password='password', + db=3 + ) + : labels: + - source: |- + Redis( + host='prod.redis.example.com', + port=6379, + password='password', + db=3 + ) + style: primary + start: 39 + end: 115 + - source: Redis + style: secondary + start: 39 + end: 44 + - source: password + style: secondary + start: 88 + end: 96 + - source: password + style: secondary + start: 98 + end: 106 + - source: '''password''' + style: secondary + start: 97 + end: 107 + - source: password='password' + style: secondary + start: 88 + end: 107 + - source: |- + ( + host='prod.redis.example.com', + port=6379, + password='password', + db=3 + ) + style: secondary + start: 44 + end: 115 + - source: from redis import Redis + style: secondary + start: 0 + end: 23 + - source: | + from redis import Redis + redis_client = Redis( + host='prod.redis.example.com', + port=6379, + password='password', + db=3 + ) + style: secondary + start: 0 + end: 116 + ? | + redis_client = redis.Redis( + host='prod.redis.example.com', + port=6379, + password='password', + db=3 + ) + : labels: + - source: |- + redis.Redis( + host='prod.redis.example.com', + port=6379, + password='password', + db=3 + ) + style: primary + start: 15 + end: 97 + - source: redis.Redis + style: secondary + start: 15 + end: 26 + - source: password + style: secondary + start: 70 + end: 78 + - source: password + style: secondary + start: 80 + end: 88 + - source: '''password''' + style: secondary + start: 79 + end: 89 + - source: password='password' + style: secondary + start: 70 + end: 89 + - source: |- + ( + host='prod.redis.example.com', + port=6379, + password='password', + db=3 + ) + style: secondary + start: 26 + end: 97 + ? | + redis_client = redis.Redis(host='10.0.0.1', port=6379, password="password") + : labels: + - source: redis.Redis(host='10.0.0.1', port=6379, password="password") + style: primary + start: 15 + end: 75 + - source: redis.Redis + style: secondary + start: 15 + end: 26 + - source: password + style: secondary + start: 55 + end: 63 + - source: password + style: secondary + start: 65 + end: 73 + - source: '"password"' + style: secondary + start: 64 + end: 74 + - source: password="password" + style: secondary + start: 55 + end: 74 + - source: (host='10.0.0.1', port=6379, password="password") + style: secondary + start: 26 + end: 75 diff --git a/tests/__snapshots__/python-requests-empty-password-python-snapshot.yml b/tests/__snapshots__/python-requests-empty-password-python-snapshot.yml new file mode 100644 index 00000000..f4fa9c2e --- /dev/null +++ b/tests/__snapshots__/python-requests-empty-password-python-snapshot.yml @@ -0,0 +1,515 @@ +id: python-requests-empty-password-python +snapshots: + ? | + asd = '' + basic = requests.auth.HTTPBasicAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + : labels: + - source: requests.auth.HTTPBasicAuth('user', asd) + style: primary + start: 17 + end: 57 + - source: requests.auth.HTTPBasicAuth + style: secondary + start: 17 + end: 44 + - source: '''user''' + style: secondary + start: 45 + end: 51 + - source: asd + style: secondary + start: 53 + end: 56 + - source: ('user', asd) + style: secondary + start: 44 + end: 57 + - source: asd + style: secondary + start: 0 + end: 3 + - source: '''''' + style: secondary + start: 6 + end: 8 + - source: asd = '' + style: secondary + start: 0 + end: 8 + - source: asd = '' + style: secondary + start: 0 + end: 8 + - source: basic = requests.auth.HTTPBasicAuth('user', asd) + style: secondary + start: 9 + end: 57 + ? | + asd = '' + basic = requests.auth.HTTPDigestAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + : labels: + - source: requests.auth.HTTPDigestAuth('user', asd) + style: primary + start: 17 + end: 58 + - source: requests.auth.HTTPDigestAuth + style: secondary + start: 17 + end: 45 + - source: '''user''' + style: secondary + start: 46 + end: 52 + - source: asd + style: secondary + start: 54 + end: 57 + - source: ('user', asd) + style: secondary + start: 45 + end: 58 + - source: asd + style: secondary + start: 0 + end: 3 + - source: '''''' + style: secondary + start: 6 + end: 8 + - source: asd = '' + style: secondary + start: 0 + end: 8 + - source: asd = '' + style: secondary + start: 0 + end: 8 + - source: basic = requests.auth.HTTPDigestAuth('user', asd) + style: secondary + start: 9 + end: 58 + ? | + asd = '' + basic = requests.auth.HTTPProxyAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + : labels: + - source: requests.auth.HTTPProxyAuth('user', asd) + style: primary + start: 17 + end: 57 + - source: requests.auth.HTTPProxyAuth + style: secondary + start: 17 + end: 44 + - source: '''user''' + style: secondary + start: 45 + end: 51 + - source: asd + style: secondary + start: 53 + end: 56 + - source: ('user', asd) + style: secondary + start: 44 + end: 57 + - source: asd + style: secondary + start: 0 + end: 3 + - source: '''''' + style: secondary + start: 6 + end: 8 + - source: asd = '' + style: secondary + start: 0 + end: 8 + - source: asd = '' + style: secondary + start: 0 + end: 8 + - source: basic = requests.auth.HTTPProxyAuth('user', asd) + style: secondary + start: 9 + end: 57 + ? | + basic = requests.auth.HTTPBasicAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + : labels: + - source: requests.auth.HTTPBasicAuth('user', '') + style: primary + start: 8 + end: 47 + - source: requests.auth.HTTPBasicAuth + style: secondary + start: 8 + end: 35 + - source: '''user''' + style: secondary + start: 36 + end: 42 + - source: '''''' + style: secondary + start: 44 + end: 46 + - source: ('user', '') + style: secondary + start: 35 + end: 47 + ? | + basic = requests.auth.HTTPDigestAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + : labels: + - source: requests.auth.HTTPDigestAuth('user', '') + style: primary + start: 8 + end: 48 + - source: requests.auth.HTTPDigestAuth + style: secondary + start: 8 + end: 36 + - source: '''user''' + style: secondary + start: 37 + end: 43 + - source: '''''' + style: secondary + start: 45 + end: 47 + - source: ('user', '') + style: secondary + start: 36 + end: 48 + ? | + basic = requests.auth.HTTPProxyAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + : labels: + - source: requests.auth.HTTPProxyAuth('user', '') + style: primary + start: 8 + end: 47 + - source: requests.auth.HTTPProxyAuth + style: secondary + start: 8 + end: 35 + - source: '''user''' + style: secondary + start: 36 + end: 42 + - source: '''''' + style: secondary + start: 44 + end: 46 + - source: ('user', '') + style: secondary + start: 35 + end: 47 + ? | + from requests.auth import HTTPBasicAuth + asd = '' + basic = HTTPBasicAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + : labels: + - source: HTTPBasicAuth('user', asd) + style: primary + start: 57 + end: 83 + - source: HTTPBasicAuth + style: secondary + start: 57 + end: 70 + - source: user + style: secondary + start: 72 + end: 76 + - source: '''user''' + style: secondary + start: 71 + end: 77 + - source: asd + style: secondary + start: 79 + end: 82 + - source: ('user', asd) + style: secondary + start: 70 + end: 83 + - source: from requests.auth import HTTPBasicAuth + style: secondary + start: 0 + end: 39 + - source: | + from requests.auth import HTTPBasicAuth + asd = '' + basic = HTTPBasicAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + style: secondary + start: 0 + end: 153 + - source: asd + style: secondary + start: 40 + end: 43 + - source: '''''' + style: secondary + start: 46 + end: 48 + - source: asd = '' + style: secondary + start: 40 + end: 48 + - source: asd = '' + style: secondary + start: 40 + end: 48 + - source: basic = HTTPBasicAuth('user', asd) + style: secondary + start: 49 + end: 83 + ? | + from requests.auth import HTTPBasicAuth + basic = HTTPBasicAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + : labels: + - source: HTTPBasicAuth('user', '') + style: primary + start: 48 + end: 73 + - source: HTTPBasicAuth + style: secondary + start: 48 + end: 61 + - source: user + style: secondary + start: 63 + end: 67 + - source: '''user''' + style: secondary + start: 62 + end: 68 + - source: '''''' + style: secondary + start: 70 + end: 72 + - source: ('user', '') + style: secondary + start: 61 + end: 73 + - source: from requests.auth import HTTPBasicAuth + style: secondary + start: 0 + end: 39 + - source: | + from requests.auth import HTTPBasicAuth + basic = HTTPBasicAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + style: secondary + start: 0 + end: 143 + ? | + from requests.auth import HTTPDigestAuth + asd = '' + basic = HTTPDigestAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + : labels: + - source: HTTPDigestAuth('user', asd) + style: primary + start: 58 + end: 85 + - source: HTTPDigestAuth + style: secondary + start: 58 + end: 72 + - source: user + style: secondary + start: 74 + end: 78 + - source: '''user''' + style: secondary + start: 73 + end: 79 + - source: asd + style: secondary + start: 81 + end: 84 + - source: ('user', asd) + style: secondary + start: 72 + end: 85 + - source: from requests.auth import HTTPDigestAuth + style: secondary + start: 0 + end: 40 + - source: | + from requests.auth import HTTPDigestAuth + asd = '' + basic = HTTPDigestAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + style: secondary + start: 0 + end: 155 + - source: asd + style: secondary + start: 41 + end: 44 + - source: '''''' + style: secondary + start: 47 + end: 49 + - source: asd = '' + style: secondary + start: 41 + end: 49 + - source: asd = '' + style: secondary + start: 41 + end: 49 + - source: basic = HTTPDigestAuth('user', asd) + style: secondary + start: 50 + end: 85 + ? | + from requests.auth import HTTPDigestAuth + basic = HTTPDigestAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + : labels: + - source: HTTPDigestAuth('user', '') + style: primary + start: 49 + end: 75 + - source: HTTPDigestAuth + style: secondary + start: 49 + end: 63 + - source: user + style: secondary + start: 65 + end: 69 + - source: '''user''' + style: secondary + start: 64 + end: 70 + - source: '''''' + style: secondary + start: 72 + end: 74 + - source: ('user', '') + style: secondary + start: 63 + end: 75 + - source: from requests.auth import HTTPDigestAuth + style: secondary + start: 0 + end: 40 + - source: | + from requests.auth import HTTPDigestAuth + basic = HTTPDigestAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + style: secondary + start: 0 + end: 145 + ? | + from requests.auth import HTTPProxyAuth + asd = '' + basic = HTTPProxyAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + : labels: + - source: HTTPProxyAuth('user', asd) + style: primary + start: 57 + end: 83 + - source: HTTPProxyAuth + style: secondary + start: 57 + end: 70 + - source: user + style: secondary + start: 72 + end: 76 + - source: '''user''' + style: secondary + start: 71 + end: 77 + - source: asd + style: secondary + start: 79 + end: 82 + - source: ('user', asd) + style: secondary + start: 70 + end: 83 + - source: from requests.auth import HTTPProxyAuth + style: secondary + start: 0 + end: 39 + - source: | + from requests.auth import HTTPProxyAuth + asd = '' + basic = HTTPProxyAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + style: secondary + start: 0 + end: 153 + - source: asd + style: secondary + start: 40 + end: 43 + - source: '''''' + style: secondary + start: 46 + end: 48 + - source: asd = '' + style: secondary + start: 40 + end: 48 + - source: asd = '' + style: secondary + start: 40 + end: 48 + - source: basic = HTTPProxyAuth('user', asd) + style: secondary + start: 49 + end: 83 + ? | + from requests.auth import HTTPProxyAuth + basic = HTTPProxyAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + : labels: + - source: HTTPProxyAuth('user', '') + style: primary + start: 48 + end: 73 + - source: HTTPProxyAuth + style: secondary + start: 48 + end: 61 + - source: user + style: secondary + start: 63 + end: 67 + - source: '''user''' + style: secondary + start: 62 + end: 68 + - source: '''''' + style: secondary + start: 70 + end: 72 + - source: ('user', '') + style: secondary + start: 61 + end: 73 + - source: from requests.auth import HTTPProxyAuth + style: secondary + start: 0 + end: 39 + - source: | + from requests.auth import HTTPProxyAuth + basic = HTTPProxyAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + style: secondary + start: 0 + end: 143 diff --git a/tests/python/python-pyjwt-hardcoded-secret-python-test.yml b/tests/python/python-pyjwt-hardcoded-secret-python-test.yml new file mode 100644 index 00000000..84dbe06a --- /dev/null +++ b/tests/python/python-pyjwt-hardcoded-secret-python-test.yml @@ -0,0 +1,23 @@ +id: python-pyjwt-hardcoded-secret-python +valid: + - | + jwt.encode({"some": "payload"}, uh, algorithm="HS256") +invalid: + - | + import os + import jwt + import jwt as lsadlsaldsa + key = "secret" + jwt.encode({"some": "payload"}, key, algorithm="HS256") + - | + import os + import jwt + import jwt as lsadlsaldsa + key = "secret" + jwt.encode({"some": "payload"}, "123", algorithm="HS256") + - | + import os + import jwt + import jwt as lsadlsaldsa + key = "secret" + lsadlsaldsa.encode({"some": "payload"}, "123", algorithm="HS256") diff --git a/tests/python/python-redis-hardcoded-secret-python-test.yml b/tests/python/python-redis-hardcoded-secret-python-test.yml new file mode 100644 index 00000000..d3fb6ece --- /dev/null +++ b/tests/python/python-redis-hardcoded-secret-python-test.yml @@ -0,0 +1,34 @@ +id: python-redis-hardcoded-secret-python +valid: + - | + redis_client = Redis( + host='localhost', + port=6379, + password=os.getenv('REDIS_PASSWORD', 'password'), + db=5 + ) +invalid: + - | + from redis import Redis + redis_client = Redis( + host='prod.redis.example.com', + port=6379, + password='password', + db=3 + ) + - | + redis_client = redis.Redis( + host='prod.redis.example.com', + port=6379, + password='password', + db=3 + ) + - | + redis_client = redis.Redis(host='10.0.0.1', port=6379, password="password") + - | + foobar = 'password' + redis_client = redis.Redis(host='1.2.3.4', password=foobar, port=6379) + - | + from redis import Redis + foobar = 'password' + redis_client = Redis(host='1.2.3.4', password=foobar, port=6379) diff --git a/tests/python/python-requests-empty-password-python-test.yml b/tests/python/python-requests-empty-password-python-test.yml new file mode 100644 index 00000000..fc985bee --- /dev/null +++ b/tests/python/python-requests-empty-password-python-test.yml @@ -0,0 +1,54 @@ +id: python-requests-empty-password-python +valid: + - | + encoded = jwt.encode({"some": "payload"}, secret_key, algorithm="HS256") + secret_const = 3 +invalid: + - | + from requests.auth import HTTPProxyAuth + asd = '' + basic = HTTPProxyAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + - | + from requests.auth import HTTPDigestAuth + asd = '' + basic = HTTPDigestAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + - | + from requests.auth import HTTPBasicAuth + asd = '' + basic = HTTPBasicAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + - | + asd = '' + basic = requests.auth.HTTPProxyAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + - | + asd = '' + basic = requests.auth.HTTPDigestAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + - | + asd = '' + basic = requests.auth.HTTPBasicAuth('user', asd) + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + - | + from requests.auth import HTTPProxyAuth + basic = HTTPProxyAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + - | + from requests.auth import HTTPDigestAuth + basic = HTTPDigestAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + - | + from requests.auth import HTTPBasicAuth + basic = HTTPBasicAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + - | + basic = requests.auth.HTTPProxyAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + - | + basic = requests.auth.HTTPDigestAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic) + - | + basic = requests.auth.HTTPBasicAuth('user', '') + requests.get('https://httpbin.org/basic-auth/user/pass', auth=basic)