GuardAPI Logo
GuardAPI

Fix SSRF (Server Side Request Forgery) in Sanic

SSRF (Server-Side Request Forgery) in Sanic environments occurs when the application accepts a user-supplied URL and fetches it without proper validation. In an async context, this allows attackers to scan internal ports, exfiltrate cloud metadata (like AWS/GCP credentials), or bypass firewalls by making the server act as a proxy into the internal network. If you are using 'httpx' or 'aiohttp' inside a Sanic route with raw user input, your internal infrastructure is exposed.

The Vulnerable Pattern

from sanic import Sanic, response
import httpx

app = Sanic(“VulnerableApp”)

@app.get(“/fetch”) async def fetch_url(request): target_url = request.args.get(“url”) async with httpx.AsyncClient() as client: # CRITICAL: No validation of the URL scheme, host, or IP range resp = await client.get(target_url) return response.text(resp.text)

The Secure Implementation

To kill SSRF, you must implement a strict validation layer before the request is initiated. The secure code does three things: 1. Scheme Enforcement: It restricts protocols to HTTP/HTTPS, preventing 'file://' or 'gopher://' attacks. 2. DNS Resolution: It resolves the hostname to an IP address immediately. 3. IP Blacklisting: It uses the 'ipaddress' module to check if the destination is a private (RFC 1918), loopback (127.0.0.1), or link-local (169.254.169.254) address. This prevents attackers from hitting internal services or cloud metadata APIs even if they use DNS rebinding or redirection.

from sanic import Sanic, response
import httpx
import ipaddress
import socket
from urllib.parse import urlparse

app = Sanic(“SecureApp”)

ALLOWED_SCHEMES = {“http”, “https”}

def is_safe_url(url): try: parsed = urlparse(url) if parsed.scheme not in ALLOWED_SCHEMES: return False

    # Resolve hostname to IP to prevent DNS Rebinding and internal access
    host_ip = socket.gethostbyname(parsed.hostname)
    ip_obj = ipaddress.ip_address(host_ip)
    
    # Block private, loopback, and link-local addresses
    if ip_obj.is_private or ip_obj.is_loopback or ip_obj.is_link_local:
        return False
    return True
except Exception:
    return False

@app.get(“/fetch”) async def fetch_url(request): target_url = request.args.get(“url”) if not is_safe_url(target_url): return response.json({“error”: “Invalid or restricted URL”}, status=403)

async with httpx.AsyncClient() as client:
    resp = await client.get(target_url)
    return response.text(resp.text)</code></pre>
System Alert • ID: 6645
Target: Sanic API
Potential Vulnerability

Your Sanic API might be exposed to SSRF (Server Side Request Forgery)

74% of Sanic apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

Free Tier • No Credit Card • Instant Report

Verified by Ghost Labs Security Team

This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.