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-002 --project .About This Rule
Understanding the vulnerability and how it is detected
Python's built-in exec() function executes dynamically constructed Python code including full statements, class and function definitions, import statements, and control flow. Unlike eval(), exec() is not restricted to expressions and can execute any valid Python code, making it significantly more dangerous.
When exec() receives a string derived from untrusted input such as HTTP parameters, file contents, environment variables, or inter-process messages, an attacker can inject arbitrary Python statements that spawn shells, exfiltrate data, install backdoors, modify the global state of the application, or execute any OS command on the host system.
There is no safe way to sandbox exec() using restricted namespace dictionaries — Python's introspection capabilities have been used to escape all known namespace-based sandboxes. The correct fix is always to avoid exec() on untrusted input entirely.
Security Implications
Potential attack scenarios if this vulnerability is exploited
Full Remote Code Execution
exec() can execute any valid Python statement, giving an attacker complete control over the process. This includes defining functions, spawning threads, importing modules, modifying global variables, and executing OS commands via os.system() or subprocess.
Application State Corruption
exec() can redefine functions, classes, and module-level variables at runtime. An attacker injecting code via exec() can replace authentication logic, disable security checks, or corrupt application state in ways that persist for the lifetime of the process.
Namespace Sandbox Escape
Attempts to restrict exec() by passing custom globals/locals dictionaries are insufficient. Python's __subclasses__(), __mro__, and __builtins__ attributes provide paths to escape any namespace restriction that has been attempted in practice.
Persistence and Lateral Movement
Through exec(), an attacker can write files to disk, modify installed packages, schedule cron jobs, and open persistent reverse shell connections that survive beyond the current request or session.
How to Fix
Recommended remediation steps
- 1Never pass user-controlled strings to exec(); there is no safe way to sandbox exec() on arbitrary input.
- 2Replace exec()-based plugin systems with importlib.import_module() restricted to an allowlist of module names.
- 3Use getattr() with explicit allowlists for dynamic method dispatch instead of constructing and exec()-ing code strings.
- 4If code generation is genuinely required, generate code at build time (not runtime) from trusted templates with no user-controlled content.
- 5Apply process isolation such as containers or separate processes with minimal privileges to limit the blast radius of any exec() exploitation.
Detection Scope
How Code Pathfinder analyzes your code for this vulnerability
This rule detects all direct calls to the built-in exec() function anywhere in Python source code, matching both unqualified exec() and builtins.exec() forms. The rule flags every call site since exec() on any dynamically constructed string is a security concern regardless of the apparent origin of the string.
Compliance & Standards
Industry frameworks and regulations that require detection of this vulnerability
References
External resources and documentation
Similar Rules
Explore related security rules for Python
Dangerous eval() Usage Detected
eval() executes arbitrary Python expressions from strings, enabling remote code execution when called with untrusted input.
Dangerous code.InteractiveConsole Usage
code.InteractiveConsole and code.interact() enable arbitrary Python code execution and should not be exposed to untrusted users.
Non-literal Dynamic Import Detected
__import__() or importlib.import_module() with a non-literal argument can import arbitrary modules when called with untrusted input.
Frequently Asked Questions
Common questions about Dangerous exec() Usage Detected
New feature
Get these findings posted directly on your GitHub pull requests
The Dangerous exec() Usage Detected rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.