HIGH ssrf server sidedjangobearer tokens

Ssrf Server Side in Django with Bearer Tokens

Ssrf Server Side in Django with Bearer Tokens — how this specific combination creates or exposes the vulnerability

Server Side Request Forgery (SSRF) in Django applications that rely on Bearer Tokens for outbound service-to-service calls can create a dangerous trust boundary issue. When an endpoint accepts user-supplied URLs and makes HTTP requests using a Bearer Token, an attacker can coerce the server into making arbitrary internal or external calls, potentially reaching metadata services or internal APIs protected by the same token scope.

Consider a Django view that fetches user data from a partner API:

import requests
def fetch_external_data(request):
    url = request.GET.get('url')
    token = request.headers.get('Authorization', '').replace('Bearer ', '')
    headers = {'Authorization': f'Bearer {token}'}
    resp = requests.get(url, headers=headers, timeout=5)
    return JsonResponse(resp.json())

If the caller provides url as http://169.254.169.254/latest/meta-data/iam/security-credentials/, the server may leak its instance credentials even though the outbound request carries a Bearer Token intended for an external API. The token is presented to the internal service, which often trusts internal metadata endpoints and may return sensitive information.

SSRF with Bearer Tokens is particularly risky when the token has broad permissions (e.g., read access to storage or compute) and the Django app is running inside a cloud environment where metadata services are reachable. An attacker might also target internal services that accept the same token audience but are not exposed externally, effectively bypassing network segmentation by abusing the Django app as a proxy.

Another variant involves OpenAPI/Swagger-driven integrations where the spec defines a security scheme using Bearer Tokens. If the implementation uses a user-supplied base URL and resolves references dynamically, an attacker could point the spec resolution to an internal host, causing the runtime to send tokens to unintended endpoints and exposing path traversal or host confusion bugs.

Because middleBrick scans the unauthenticated attack surface and includes SSRF among its 12 parallel checks, it can detect whether a Bearer Token–protected endpoint is susceptible to SSRF by probing with internal and external malicious targets. Findings are mapped to OWASP API Top 10 and include remediation guidance, helping teams understand the risk without relying on internal architecture details.

Bearer Tokens-Specific Remediation in Django — concrete code fixes

To mitigate SSRF when using Bearer Tokens in Django, you must validate and restrict outbound destinations and avoid forwarding tokens to untrusted hosts. Below are concrete, secure code examples.

1. Strict URL allowlist

Only permit calls to known, pre-approved hosts. Do not rely on path or query parameters to decide reachability.

import requests
from urllib.parse import urlparse
ALLOWED_HOSTS = {'api.example.com', 'data.partner.com'}
def fetch_external_data(request):
    url = request.GET.get('url')
    parsed = urlparse(url)
    if parsed.netloc not in ALLOWED_HOSTS:
        return JsonResponse({'error': 'destination not allowed'}, status=400)
    token = request.headers.get('Authorization', '').replace('Bearer ', '')
    headers = {'Authorization': f'Bearer {token}'}
    resp = requests.get(url, headers=headers, timeout=5)
    return JsonResponse(resp.json())

2. Token scoping and outbound destination segregation

Do not reuse the same Bearer Token for calls to external APIs and internal services. Issue short-lived tokens scoped only to the intended audience and keep internal services on separate network zones.

import requests
def call_partner_api(resource, token):
    url = f'https://api.example.com/{resource}'
    headers = {'Authorization': f'Bearer {token}'}
    resp = requests.get(url, headers=headers, timeout=5)
    resp.raise_for_status()
    return resp.json()

In this pattern, the token is obtained for a specific partner audience and never used to reach internal metadata or administrative endpoints. If you rely on OpenAPI specs, ensure that host resolution is static and not derived from user input.

3. Disallow private IPs and localhost

Reject requests that target RFC 1918 ranges, loopback, or link-local addresses.

import requests
from ipaddress import ip_address, IPv4Address
def is_private_ip(host: str) -> bool:
    try:
        ip = ip_address(host)
        return ip.is_private
    except ValueError:
        return False
def fetch_external_data(request):
    url = request.GET.get('url')
    parsed = urlparse(url)
    if is_private_ip(parsed.hostname):
        return JsonResponse({'error': 'private destination not allowed'}, status=400)
    token = request.headers.get('Authorization', '').replace('Bearer ', '')
    headers = {'Authorization': f'Bearer {token}'}
    resp = requests.get(url, headers=headers, timeout=5)
    return JsonResponse(resp.json())

These measures reduce the attack surface significantly. For continuous assurance, integrate middleBrick CLI to scan from terminal with middlebrick scan <url> or add the GitHub Action to your CI/CD pipeline to fail builds if security scores drop below your chosen threshold. Teams using the Pro plan can enable continuous monitoring and receive Slack or Teams alerts when SSRF or other high-severity findings appear.

Frequently Asked Questions

Does middleBrick fix SSRF vulnerabilities in Django apps?
middleBrick detects and reports SSRF findings with severity, impact, and remediation guidance. It does not automatically fix or patch your code; developers must apply the recommended changes.
Can the GitHub Action prevent deployments if Bearer Token–protected endpoints are vulnerable to SSRF?
Yes. The GitHub Action can be configured as a PR gate to fail builds when the security score drops below your defined threshold, helping prevent vulnerable code from merging.