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-021 --project .About This Rule
Understanding the vulnerability and how it is detected
Calling subprocess functions with shell=True passes the command to the system shell (/bin/sh on Unix, cmd.exe on Windows) for interpretation before execution. This means all shell metacharacters — semicolons, pipes, backticks, dollar signs, redirections, and command substitutions — are interpreted by the shell.
When any component of the command string is derived from untrusted input, an attacker can inject shell metacharacters to execute additional commands, redirect output, or access the shell's full feature set. This is equivalent in risk to calling os.system() with user input.
The fix is to remove shell=True and pass the command as a list of arguments. When a shell pipeline is genuinely required, ensure every element is either a hardcoded literal or validated against a strict allowlist.
Security Implications
Potential attack scenarios if this vulnerability is exploited
Shell Metacharacter Injection
With shell=True, characters like ; | && || ` $() >> < and newlines are interpreted by the shell. An attacker injecting these characters into any part of the command string can chain additional commands, redirect output to arbitrary files, or access subshell features.
Environment Variable Expansion
The shell expands $VAR and ${VAR} expressions in the command string. If user input contains these patterns, the shell may expand them to sensitive environment variable values, leak credentials, or change command behavior based on environment state.
Glob and Brace Expansion
Shell glob expansion (*, ?, []) and brace expansion ({a,b}) in user input can cause the command to process unintended files or generate unexpected argument lists, leading to information disclosure or unintended file operations.
Bypass of Input Validation
Input validation for shell=True is extremely difficult to implement correctly because shell quoting rules vary by shell, context, and locale. Validation based on blocklists of shell metacharacters routinely misses edge cases. The only reliable mitigation is to remove shell=True.
How to Fix
Recommended remediation steps
- 1Remove shell=True from all subprocess calls that process any user-controlled input; use a list of arguments with shell=False instead.
- 2For shell pipelines, implement the pipeline in Python using subprocess.PIPE to connect processes without invoking a shell.
- 3If shell=True is unavoidable, ensure every component of the command string is a hardcoded literal with no user-controlled content.
- 4Use shlex.split() to tokenize a trusted shell command string into a list for use with shell=False.
- 5Set the input, stdout, stderr, and timeout parameters explicitly on all subprocess calls to prevent resource leaks and information exposure.
Detection Scope
How Code Pathfinder analyzes your code for this vulnerability
This rule detects calls to subprocess.run(), subprocess.call(), subprocess.check_call(), subprocess.check_output(), and subprocess.Popen() that include the keyword argument shell=True or a positional True value in the shell parameter position. The rule flags all such calls since shell=True always routes the command through the system shell.
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 os.system() or os.popen() Call
os.system() and os.popen() execute shell commands via /bin/sh, enabling command injection when arguments contain untrusted input.
Dangerous subprocess Usage
subprocess calls detected. Ensure command arguments are not user-controlled to prevent OS command injection.
Dangerous asyncio Shell Execution
asyncio.create_subprocess_shell() passes the command through the system shell, enabling command injection when arguments contain untrusted input.
Frequently Asked Questions
Common questions about subprocess Called with shell=True
New feature
Get these findings posted directly on your GitHub pull requests
The subprocess Called with shell=True rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.