python.lang.security.audit.dangerous-annotations-usage.dangerous-annotations-usage
semgrep
Author
1,829
Download Count*
License
Annotations passed to typing.get_type_hints
are evaluated in globals
and locals
namespaces. Make sure that no arbitrary value can be written as the annotation and passed to typing.get_type_hints
function.
Run Locally
Run in CI
Defintion
rules:
- id: dangerous-annotations-usage
patterns:
- pattern: |
$C.__annotations__[$NAME] = $X
- pattern-not: |
$C.__annotations__[$NAME] = "..."
- pattern-not: |
$C.__annotations__[$NAME] = typing.$Y
- metavariable-regex:
metavariable: $X
regex: (?!(int|float|complex|list|tuple|range|str|bytes|bytearray|memoryview|set|frozenset|dict))
message: Annotations passed to `typing.get_type_hints` are evaluated in
`globals` and `locals` namespaces. Make sure that no arbitrary value can
be written as the annotation and passed to `typing.get_type_hints`
function.
severity: INFO
metadata:
cwe:
- "CWE-95: Improper Neutralization of Directives in Dynamically
Evaluated Code ('Eval Injection')"
owasp:
- A03:2021 - Injection
category: security
references:
- https://docs.python.org/3/library/typing.html#typing.get_type_hints
technology:
- python
subcategory:
- audit
likelihood: LOW
impact: LOW
confidence: LOW
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Code Injection
languages:
- python
Examples
dangerous-annotations-usage.py
from typing import List, Set, Dict, Tuple, Optional, get_type_hints
class C:
member: int = 0
def smth(payload):
# ruleid: dangerous-annotations-usage
C.__annotations__["member"] = payload
get_type_hints(C)
def ok1():
# ok: dangerous-annotations-usage
C.__annotations__["member"] = int
get_type_hints(C)
def ok2():
# ok: dangerous-annotations-usage
C.__annotations__["member"] = List
get_type_hints(C)
Short Link: https://sg.run/8R6J