Token Leakage in Django with Hmac Signatures
Token Leakage in Django with Hmac Signatures — how this specific combination creates or exposes the vulnerability
Token leakage in Django when using HMAC signatures typically occurs at the intersection of session management, signed cookies, and cryptographic nonces. HMAC signatures in Django are commonly used to guarantee integrity for values stored in cookies or URLs, such as signed session identifiers or one-time tokens generated with django.core.signing.Signer or TimestampSigner. If these signed values are transmitted over insecure channels, logged inadvertently, or embedded in referrer headers, the token can be exposed despite the signature protecting its integrity.
A concrete scenario: a Django view generates a signed redirect token containing a user ID and expiration, using TimestampSigner with a project-wide secret key. If the application places this token in a URL and the user’s browser leaks the Referer header to third‑party sites or logs, the token is exposed. An attacker who obtains the token can attempt offline replay if the signature verification does not enforce strict one‑time use or nonce checks. Additionally, if the signing key is weak, stored in source control, or accidentally exposed in error messages, the signature provides no protection against tampering, and the token value itself may be extracted from logs or client‑side storage.
Another vector arises when HMAC signatures are used for API tokens or webhook payloads. If Django serializes sensitive data, signs it with HMAC, and then includes the raw payload plus signature in an HTTP header or query parameter, any side‑channel that exposes the header (e.g., logs, browser dev tools, or MITM on unencrypted transport) results in token leakage. The signature ensures the payload has not been altered, but it does not prevent exposure; confidentiality must be provided by transport security (TLS) and disciplined handling of secrets. Misconfigured CORS or overly permissive CSP can also cause browsers to leak signed tokens via JavaScript origins or embedded scripts.
To detect this pattern, middleBrick’s LLM/AI Security checks look for system prompt leakage and active prompt injection probes, which are unrelated to HMAC token handling but illustrate how exposure pathways are validated. In the context of API scanning, findings related to Token Leakage focus on whether signed tokens can be extracted from client‑side artifacts, logs, or unauthenticated endpoints, and whether replay or tampering risks exist when signatures are not paired with strict nonce or replay protection.
Hmac Signatures-Specific Remediation in Django — concrete code fixes
Remediation centers on disciplined use of cryptographic primitives, secure transport, and minimizing the scope and lifetime of signed tokens. Below are concrete, realistic code examples for Django that demonstrate how to use HMAC signatures safely.
Secure signed value generation and verification
Use TimestampSigner to include expiration and detect replay within a time window. Always set a short validity period and avoid embedding highly sensitive data in the payload.
from django.core.signing import TimestampSigner, BadSignature, SignatureExpired
import django
from django.conf import settings
signer = TimestampSigner(key=settings.SECRET_KEY)
# Create a signed token with a short validity (e.g., 5 minutes)
token = signer.sign_object(
{"user_id": 123, "action": "email_verify"},
salt="email_confirm",
max_age=60 * 5 # seconds
)
# In the receiving view, verify and handle expiry/tampering
try:
data = signer.unsign_object(token, salt="email_confirm")
except SignatureExpired:
# Handle expired token: reject and optionally request new one
raise ValueError("Token expired")
except BadSignature:
raise ValueError("Invalid signature")
Avoid logging and minimize exposure
Ensure signed tokens are not written to application logs or error messages. If you must log for debugging, redact or hash the token.
import logging
logger = logging.getLogger(__name__)
def my_view(request):
token = request.GET.get("token")
# Never log raw token
logger.info("Token received", extra={"token_hash": hash(token)})
# Process token securely
Transport and host hardening
Serve all token-bearing endpoints over TLS, set Secure and HttpOnly flags on cookies, and configure CORS narrowly.
# settings.py
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_HTTPONLY = True
CSRF_COOKIE_HTTPONLY = True
# CORS configuration example for django-cors-headers
CORS_ALLOWED_ORIGINS = [
"https://app.example.com",
]
Replay protection with one‑time nonces
For high‑risk operations, pair HMAC signatures with server‑side nonce storage (e.g., Redis) to prevent replay within the validity window.
import time
import hashlib
from django.core.cache import cache
def verify_nonce(token_nonce):
if cache.get(f"used_nonce:{token_nonce}"):
raise ValueError("Replay detected")
cache.set(f"used_nonce:{token_nonce}", True, timeout=600)
middleBrick’s GitHub Action can be added to CI/CD pipelines to fail builds if risk scores exceed your threshold, helping you catch insecure token handling before deployment. The dashboard allows you to track how remediation impacts your security posture over time.