Dangerous typing.get_type_hints() Usage

MEDIUM

typing.get_type_hints() evaluates string annotations as Python expressions, enabling code execution when annotation strings contain untrusted content.

Rule Information

Language
Python
Category
Python Core
Author
Shivasurya
Shivasurya
Last Updated
2026-03-22
Tags
pythonannotationsget-type-hintspep-563type-evaluationCWE-95OWASP-A03
CWE References

Interactive Playground

Experiment with the vulnerable code and security rule below. Edit the code to see how the rule detects different vulnerability patterns.

pathfinder scan --ruleset python/PYTHON-LANG-SEC-006 --project .
1
2
3
4
5
6
7
8
9
rule.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

About This Rule

Understanding the vulnerability and how it is detected

Python's typing.get_type_hints() resolves type annotations by evaluating string annotations (also known as PEP 563 postponed annotations) using eval() in the context of the annotated object's module namespace. When from __future__ import annotations is used or annotations are stored as string literals, get_type_hints() calls eval() on those strings to resolve them.

If annotations are dynamically constructed or sourced from untrusted data, an attacker can inject arbitrary Python expressions into the annotation string that will be evaluated when get_type_hints() is called. This is particularly relevant in frameworks that use annotations for serialization, validation, or ORM field definitions and call get_type_hints() at runtime.

In most applications, get_type_hints() is called on developer-controlled class definitions and poses no direct risk. The risk arises when annotation strings are generated dynamically from external input or when get_type_hints() is called on classes loaded from untrusted sources.

Security Implications

Potential attack scenarios if this vulnerability is exploited

1

Annotation String Evaluation

With from __future__ import annotations enabled, all annotations are stored as strings and evaluated lazily. get_type_hints() calls eval() on these strings. If annotation strings can be influenced by an attacker, this becomes an eval injection vulnerability.

2

Framework-Level Risk in Pydantic and Dataclasses

Frameworks such as pydantic, dataclasses, and attrs call get_type_hints() to resolve field types. If these frameworks process class definitions constructed from external data, the annotation evaluation can be exploited. This is a known risk in dynamic schema generation.

3

Serialization and ORM Reflection Attacks

ORMs and serialization libraries that use annotations to determine field types and call get_type_hints() for schema reflection can be attacked via malicious annotation strings in serialized object metadata.

4

Plugin and Extension Loading

Systems that dynamically load classes from user-specified modules and then call get_type_hints() on those classes for introspection may execute malicious annotation expressions defined in attacker-controlled plugin code.

How to Fix

Recommended remediation steps

  • 1Only call get_type_hints() on classes and functions defined in trusted, version-controlled source code.
  • 2Never construct annotation strings dynamically from external input or store annotation strings in untrusted data sources.
  • 3When building dynamic schemas from external configuration, use typing constructs as Python objects (str, int, List[str]) rather than string representations.
  • 4Audit frameworks that call get_type_hints() on plugin or user-defined classes to ensure annotation content cannot be influenced by attackers.
  • 5Consider using inspect.get_annotations() in Python 3.10+ for lower-level annotation access that avoids the eval() behavior in specific contexts.

Detection Scope

How Code Pathfinder analyzes your code for this vulnerability

This rule detects calls to typing.get_type_hints() and the unqualified form get_type_hints() in Python source code. The rule flags all call sites for review since the safety depends on the trust level of the object passed as the argument, which requires human review to determine.

Compliance & Standards

Industry frameworks and regulations that require detection of this vulnerability

CWE Top 25
CWE-95 - Eval Injection in the MITRE CWE Top 25 Most Dangerous Software Weaknesses
OWASP Top 10
A03:2021 - Injection
NIST SP 800-53
SI-10: Information Input Validation
PCI DSS v4.0
Requirement 6.2.4 - Protect web-facing applications against injection attacks

References

External resources and documentation

Similar Rules

Explore related security rules for Python

Frequently Asked Questions

Common questions about Dangerous typing.get_type_hints() Usage

No. When called on developer-defined classes whose annotations are written directly in source code, get_type_hints() is safe. The risk is only present when the object being inspected has annotations that were constructed from external input or loaded from an untrusted source.
PEP 563 (from __future__ import annotations) changes Python to store all annotations as strings rather than evaluating them at class definition time. get_type_hints() then evaluates these strings lazily. This defers the evaluation, which means that any dynamically constructed annotation string that contains malicious content is not executed until get_type_hints() is called.
Pydantic v2 uses its own annotation resolution mechanism (pydantic._internal._generate_schema) that is separate from typing.get_type_hints(). Pydantic v1 uses get_type_hints() for model field resolution. In both cases, if models are dynamically constructed from untrusted data, the annotation resolution can be exploited. Prefer defining pydantic models statically in source code.
Python 3.11+ (and PEP 649 in Python 3.14) introduces deferred annotation evaluation with a different mechanism that does not immediately eval all annotation strings. However, get_type_hints() still evaluates annotation strings, so the risk remains whenever get_type_hints() is explicitly called on objects with string annotations.
Yes. Framework initialization code that calls get_type_hints() on statically defined model classes during application startup is generally safe. Document the suppression with the classes being inspected and confirmation that their annotations cannot be influenced by external input at runtime.
inspect.get_annotations() (Python 3.10+) returns the raw annotation dictionary without evaluating string annotations. It is safer when you only need the raw annotation strings for documentation or metadata purposes, not for type resolution. Use it when get_type_hints() evaluation is not needed.

New feature

Get these findings posted directly on your GitHub pull requests

The Dangerous typing.get_type_hints() Usage rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.

See how it works