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-FLASK-SEC-006 --project .About This Rule
Understanding the vulnerability and how it is detected
This rule detects Server-Side Request Forgery (SSRF) in Flask applications where user-controlled input from HTTP request parameters flows into outbound HTTP request URLs via the requests library (requests.get, requests.post, requests.put, requests.delete, requests.patch, requests.head, requests.options) or the standard library (urllib.request.urlopen, urllib.request.Request).
SSRF allows attackers to instruct the application server to make HTTP requests to destinations of the attacker's choosing. The server then acts as a proxy, forwarding the response to the attacker. This is particularly severe in cloud environments where the EC2/ECS/GKE metadata endpoint (169.254.169.254) returns instance credentials without authentication when reached from the instance itself.
The rule uses taint analysis to trace the URL argument from Flask request sources through variable assignments and function calls. The .tracks(0) parameter targets the URL positional argument to requests functions, where SSRF occurs. Flows through validate_url() or is_safe_url() are recognized as sanitizers because these functions typically implement allowlist-based URL validation.
Security Implications
Potential attack scenarios if this vulnerability is exploited
Cloud Instance Credential Theft
In AWS, GCP, and Azure, the instance metadata service is accessible at http://169.254.169.254/ (or http://169.254.169.254/latest/meta-data/iam/ security-credentials/ on AWS). An attacker who controls the URL parameter causes the Flask server to fetch its own IAM credentials and return them in the response. These credentials give the attacker full API access to the cloud account.
Internal Service Discovery and Exploitation
The application server can reach internal services on the private network that are not exposed to the internet: internal APIs, admin dashboards, Kubernetes API servers, Redis instances, and Elasticsearch clusters. SSRF turns an external attacker into an internal network attacker with the server's identity.
Port Scanning and Network Topology Mapping
Timing differences in SSRF responses reveal which internal hosts and ports are open. An attacker iterates RFC 1918 addresses and observes connection timeouts vs. refused connections to map the internal network topology, identifying targets for subsequent exploitation.
Bypassing IP-Based Access Controls
Many internal services restrict access by source IP address, trusting requests from the application server. SSRF bypasses this control because the request originates from the trusted server. Admin interfaces that are secure against external access become reachable via the vulnerable Flask endpoint.
How to Fix
Recommended remediation steps
- 1Implement an allowlist of trusted hostnames that the application is permitted to request, and reject any URL whose host is not on the list.
- 2Resolve the DNS name to an IP address after allowlist validation and verify the resolved IP is not in a private, loopback, or link-local range to prevent DNS rebinding attacks.
- 3Disable redirects or validate redirect destinations against the allowlist -- requests follows redirects by default and a redirect to 169.254.169.254 bypasses the initial URL check.
- 4Use a dedicated HTTP client configured to reject private IP ranges at the network level (e.g., SSRF-aware proxy like Smokescreen) rather than relying solely on application-level validation.
- 5Set short timeouts and response size limits on outbound requests to limit damage from requests to slow internal services.
Detection Scope
How Code Pathfinder analyzes your code for this vulnerability
Scope: global (cross-file taint tracking across the entire project). Sources: Flask HTTP input methods -- request.args.get(), request.form.get(), request.values.get(), request.get_json() -- all of which can deliver attacker- controlled URL strings. Sinks: requests.get(), requests.post(), requests.put(), requests.delete(), requests.patch(), requests.head(), requests.options() -- and stdlib equivalents urllib.request.urlopen() and urllib.request.Request(). The .tracks(0) parameter targets the URL argument at position 0, the destination that determines where the server sends the request. Sanitizers: validate_url() and is_safe_url() are recognized as sanitizing functions. These typically implement allowlist checks against a set of trusted hostnames. A flow through either function before reaching a requests sink is treated as sanitized. The rule follows URL values through variable assignments and cross-file function calls, catching SSRF patterns where the URL is assembled in a utility function separate from the Flask route handler.
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
Flask SSRF via Tainted URL Host
User input from Flask request parameters is used to construct the host component of an outbound HTTP request URL. Validate the host against an explicit allowlist before making server-side requests.
Django Tainted SQL String Construction
User input is used to construct a SQL string that flows to a database execution function, enabling SQL injection via string building.
Lambda Command Injection via asyncio.create_subprocess_exec()
Lambda event data flows to asyncio.create_subprocess_exec(), enabling argument injection in async Lambda handlers.
Frequently Asked Questions
Common questions about Flask SSRF via requests Library
New feature
Get these findings posted directly on your GitHub pull requests
The Flask SSRF via requests Library rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.