SSRF

SSRF in Flask: Remediation Guide [CVE-2021-42079]

[Updated Jun 2026] Updated CVE-2021-42079

Overview

In CVE-2021-42079, an authenticated administrator could craft an alert that caused the backend to perform a request to attacker-controlled endpoints, enabling an SSRF attack. This vulnerability stemmed from accepting untrusted input to drive outbound connections in a POST-based workflow; the attacker could place a URL or destination in the alert configuration and trigger it later via a POST, effectively instructing the server to contact arbitrary resources. The risk is high because it leverages the server's network privileges and can reach internal services or sensitive endpoints. In Flask-style apps, SSRF patterns occur when endpoints take a URL-like parameter from the client or admin to fetch or forward data or to dispatch webhooks. If those inputs are not validated and restricted, an attacker with legitimate access can cause the application to reach internal networks, perform port scans, or exfiltrate data by proxying requests through the app's process. The CVE highlights the danger of combining authentication with flexible destinations in API workflows. To fix in real Flask code, avoid using user-supplied URLs for outbound requests. Implement server-side allowlists of hosts and enforce strict URL validation, disallow redirects, and set reasonable timeouts. Ensure only trusted, authenticated users (e.g., admins) can configure endpoints that trigger outbound requests. Use a dedicated component to handle outbound requests with strict policies, and log/monitor SSRF attempts. Consider proxies and network ACLs to constrain egress and reduce blast radius. Additionally, write tests, add monitoring and auditing, patch dependencies, and review security defaults and dependency trees to prevent regressions.

Code Fix Example

Flask API Security Remediation
def vulnerable_fetch(url):
    import requests
    r = requests.get(url, timeout=5)
    return r.text

from flask import Flask, request
app = Flask(__name__)

@app.route('/fetch')
def fetch_route():
    url = request.args.get('url')
    return vulnerable_fetch(url)

# FIX: whitelist hosts, validate URL, disable redirects, and restrict to trusted destinations
from urllib.parse import urlparse
ALLOWED_HOSTS = {'trusted.example.com', 'api.example.com'}

def secure_fetch(url):
    if not url:
        raise ValueError('Missing URL')
    parsed = urlparse(url)
    if parsed.scheme not in ('http', 'https'):
        raise ValueError('Unsupported URL scheme')
    if parsed.hostname not in ALLOWED_HOSTS:
        raise ValueError('Host not allowed')
    r = requests.get(url, timeout=5, allow_redirects=False)
    return r.text

@app.route('/fetch-secure')
def fetch_secure_route():
    url = request.args.get('url')
    try:
        return secure_fetch(url)
    except Exception as e:
        return str(e), 400

CVE References

Choose which optional cookies to allow. You can change this any time.