Instruction file imported from DataDog/dd-trace-py (
.cursor/rules/iast.mdc). Copyright stays with the author.
IAST Development Guide
Note: General development patterns, code style, and testing guidelines are in AGENTS.md under "IAST/AppSec Development".
Synonyms: IAST = Code Security = Runtime Code Analysis (all refer to the same product)
What is IAST?
IAST (Interactive Application Security Testing) analyzes running Python applications for security vulnerabilities by:
- Taint tracking - Performing taint analysis on data from untrusted sources (user input, HTTP requests, etc.)
- Detecting vulnerabilities - Identifying when tainted data reaches security-sensitive functions (sinks)
Official Documentation:
- Datadog Code Security (IAST) Overview
- Getting Started with Code Security
- Understanding Vulnerability Types
How IAST Works: High-Level Architecture
1. AST Patching (Code Instrumentation)
IAST modifies Python bytecode at import time using AST (Abstract Syntax Tree) patching:
- Module Watchdog: Hooks into Python's import system (
ddtrace.internal.module.ModuleWatchdog) - AST Visitor: Analyzes and modifies Python AST before compilation (
ddtrace/appsec/_iast/_ast/visitor.py) - String Operations: Patches string operations (concat, slice, format, etc.) to propagate taint
- Call Sites: Instruments function calls to track taint flow
Location: ddtrace/appsec/_iast/_ast/
ast_patching.py- Main AST patching logicvisitor.py- AST visitor for code transformationiastpatch.c- C extension for fast AST manipulation
Activation: Via ModuleWatchdog.register_pre_exec_module_hook() in ddtrace/appsec/_iast/__init__.py
2. Taint Tracking (C++ Native Extension)
Taint information is stored and propagated efficiently using a C++ native extension:
- TaintedObject: Associates Python objects with taint metadata (source, ranges)
- Taint Ranges: Track which parts of strings/bytes are tainted
- Context Management: Per-request taint state using context-local storage
- Propagation Aspects: Functions that propagate taint through operations
Location: ddtrace/appsec/_iast/_taint_tracking/
- Native C++ code compiled with CMake
aspects.py- Python API for taint propagation_native.cpython-*.so- Compiled C++ extension
Key Concepts:
- Taint Source: Where untrusted data enters (HTTP params, headers, body)
- Taint Propagation: Following data through operations (concat, slice, replace, etc.)
- Taint Range: Start/end positions in strings that are tainted
3. Module Patching (Taint Sinks)
IAST wraps security-sensitive functions to detect vulnerabilities:
- IASTFunction: Wraps target functions using
wraptlibrary - Taint Sinks: Security-sensitive functions (exec, eval, SQL, file operations, etc.)
- Vulnerability Detection: Checks if tainted data reaches sinks
Location: ddtrace/appsec/_iast/_patch_modules.py
Supported Vulnerability Types (ddtrace/appsec/_iast/taint_sinks/):
sql_injection.pycommand_injection.pypath_traversal.pyssrf.pycode_injection.pyheader_injection.pyweak_hash.pyweak_cipher.pyweak_randomness.pyinsecure_cookie.pyunvalidated_redirect.pyuntrusted_serialization.py
4. Overhead Control Engine (OCE)
Performance optimization to limit IAST overhead:
- Request Sampling: Analyze only X% of requests (default: 30%)
- Vulnerability Limits: Max vulnerabilities per request
- Concurrent Request Limits: Max requests analyzed simultaneously
- Per-Vulnerability Quotas: Limit overhead per vulnerability type
Location: ddtrace/appsec/_iast/_overhead_control_engine.py
Configuration: Settings defined in ddtrace/internal/settings/asm.py (e.g., _iast_request_sampling, _iast_sink_points_enabled)
5. Vulnerability Reporting
When a vulnerability is detected:
- Evidence is collected (tainted data, location, stack trace)
- Vulnerability is reported via the tracer span
- Deduplication prevents duplicate reports
- Data is sent to Datadog backend for analysis
Key IAST Concepts for Development
Taint Tracking Terminology
- Taint Sources (Origins): Where untrusted data enters the application (HTTP params, headers, body, cookies)
- Taint Propagation: How tainted data flows through string operations (concat, slice, replace, format, etc.)
- Taint Ranges: Specific byte/character offsets within strings that are tainted (start position + length)
- Sink Points: Security-sensitive functions where vulnerabilities are detected (SQL execute, OS commands, file operations, eval/exec)
- Update Origins: Adding or modifying taint source information to track data lineage
Call Site Instrumentation
IAST uses Call Site Instrumentation (CSI) instead of traditional callee instrumentation:
- Modifies calls to target functions rather than the functions themselves
- Enables selective instrumentation based on context (e.g., skip internal JVM/framework calls)
- Reduces overhead by instrumenting only application code, not low-level library internals
Tainted Ranges and Offsets
Ranges track which parts of strings contain tainted data:
- Offset: Starting position of tainted substring (encoding-dependent: UTF-16, Unicode code points, or bytes)
- Length: Size of tainted region
- Source: Reference to the origin of the tainted data
- Used in vulnerability evidence to highlight exactly which user input caused the issue
Security Controls (Validators & Sanitizers)
User-configurable validation/sanitization functions that apply secure marks to tainted ranges:
- Input Validators: Check if input is safe, apply marks to input arguments
- Sanitizers: Transform input to make it safe, apply marks to return value
- Secure Marks: Flags indicating a range is safe for specific vulnerability types
- If all ranges reaching a sink have appropriate secure marks, the vulnerability is suppressed
Vulnerability Detection Flow
- Taint data at sources - Mark HTTP request data with origin information
- Propagate through operations - Track tainted ranges through string manipulations via aspects
- Check at sink points - When tainted data reaches a vulnerable function, report if not secured
- Apply overhead controls - Request sampling, vulnerability quotas, and deduplication limit impact
Implementation References
- Taint Sinks:
ddtrace/appsec/_iast/taint_sinks/- Each file handles a specific vulnerability type - Aspects:
ddtrace/appsec/_iast/_taint_tracking/aspects.py- Propagation functions for string operations - Patch Modules:
ddtrace/appsec/_iast/_patch_modules.py- Registry of instrumented sink points - Vulnerability Base:
ddtrace/appsec/_iast/taint_sinks/_base.py- Base class for all vulnerability types
Important Technical Details
Flask Applications
Flask apps need special patching for main module instrumentation:
from ddtrace.appsec._iast import ddtrace_iast_flask_patch
if __name__ == "__main__":
ddtrace_iast_flask_patch() # Call before app.run()
app.run()
This patches the main Flask app file so IAST works on functions defined in app.py.
Gevent Compatibility
IMPORTANT: Avoid top-level import inspect in IAST code - it interferes with gevent's monkey patching and causes sporadic worker timeouts in Gunicorn applications.
Solution: Import inspect locally within functions when needed.
Native Code Development
When working with IAST's C++ taint tracking code:
- Prefer: Native C++ types (
std::string,int,char) - If needed: CPython API with
PyObject*(careful with reference counting!) - Last resort: Pybind11 (adds complexity)
Build & Test C++ Code:
cmake -DCMAKE_BUILD_TYPE=Debug -DPYTHON_EXECUTABLE=python \
-S ddtrace/appsec/_iast/_taint_tracking \
-B ddtrace/appsec/_iast/_taint_tracking
make -f ddtrace/appsec/_iast/_taint_tracking/tests/Makefile native_tests
ddtrace/appsec/_iast/_taint_tracking/tests/native_tests
Testing IAST Code
Python Tests
# Run IAST tests
python -m pytest -vv -s --no-cov tests/appsec/iast/
# Run specific vulnerability tests
python -m pytest -vv tests/appsec/iast/taint_sinks/test_sql_injection.py
# Run with IAST enabled
DD_IAST_ENABLED=true python -m pytest tests/appsec/iast/
End-to-End Tests
E2E tests use test servers defined in tests/appsec/appsec_utils.py:
django_server- Django test applicationflask_server- Flask test applicationfast_api- FastAPI test application
Test application location: tests/appsec/integrations/django_tests/django_app
Running E2E tests:
# Start testagent
docker compose up -d testagent
# Run E2E tests
python -m pytest tests/appsec/iast/test_integration.py -v
C++ Native Tests
# Build and run C++ tests
./ddtrace/appsec/_iast/_taint_tracking/tests/native_tests
Key Files Reference
Core Implementation:
ddtrace/appsec/_iast/__init__.py- Entry point, initialization, fork safetyddtrace/appsec/_iast/_overhead_control_engine.py- Performance control (OCE)ddtrace/appsec/_iast/_patch_modules.py- Module patching registry
AST Patching:
ddtrace/appsec/_iast/_ast/ast_patching.py- AST transformationddtrace/appsec/_iast/_ast/visitor.py- AST visitorddtrace/appsec/_iast/_loader.py- Patched module execution
Taint Tracking:
ddtrace/appsec/_iast/_taint_tracking/- C++ native taint trackingddtrace/appsec/_iast/_taint_tracking/aspects.py- Taint propagation API
Vulnerability Detection:
ddtrace/appsec/_iast/taint_sinks/- All vulnerability detectorsddtrace/appsec/_iast/taint_sinks/_base.py- Base vulnerability class
Security Controls:
ddtrace/appsec/_iast/secure_marks/- Validators and sanitizers
Environment Variables
Public Configuration: All public IAST environment variables are documented in the ddtrace Configuration Guide.
Private/Internal Environment Variables (for development and debugging):
# Enable debug-level taint propagation logging
_DD_IAST_PROPAGATION_DEBUG=true
# Enable IAST internal debug logging
_DD_IAST_DEBUG=true
# Enable specific taint sink detection (comma-separated list)
_DD_IAST_SINK_POINTS_ENABLED=sql_injection,command_injection,path_traversal
# Specify modules to patch for AST instrumentation
_DD_IAST_PATCH_MODULES=benchmarks.,tests.appsec.,scripts.iast.
# Fast build mode - skips some compilation optimizations (development only)
DD_FAST_BUILD=1
Note: Private environment variables (prefixed with _DD_) are not officially supported and may change without notice. They are primarily for internal development and debugging.