HIGH data exposuredjangobearer tokens

Data Exposure in Django with Bearer Tokens

Data Exposure in Django with Bearer Tokens

Bearer tokens are commonly used to protect APIs by requiring a token in the Authorization header. In Django, if token validation is incomplete or tokens are handled carelessly, sensitive data can be exposed. A typical misconfiguration occurs when views or middleware do not properly restrict access to endpoints, allowing an unauthenticated or low-privilege actor to read or intercept token-protected resources.

Data exposure with Bearer tokens in Django can happen when responses include sensitive fields (e.g., email, internal IDs, tokens) in JSON serialization, or when debug settings inadvertently leak information in error pages. For example, if a Django REST Framework (DRF) serializer does not explicitly exclude sensitive attributes, those fields may be returned to any client that presents a valid token obtained through other means. This violates the principle of least privilege and can lead to account enumeration or data exfiltration.

Another exposure path involves logging. If Bearer tokens or user identifiers are written to application logs without redaction, tokens can be persisted in log files and later accessed by unauthorized parties. Similarly, improper CORS settings can allow browser-based JavaScript to make authenticated requests to your Django backend from unintended origins, expanding the exposure surface beyond intended clients.

Middleware that does not validate token scope or audience can also contribute to data exposure. A token issued for one API or service might be accepted by another endpoint within the same Django project if scope checks are omitted. This becomes critical when token introspection or revocation mechanisms are not implemented, as a stolen token may remain usable for extended periods.

middleBrick scans for these classes of risk under Data Exposure by correlating runtime behavior with OpenAPI specifications, including how authentication schemes are defined and which endpoints require authorization. It checks whether responses inadvertently include sensitive data structures and whether security headers that mitigate exposure are present. These checks are performed without requiring authentication, focusing on the unauthenticated attack surface to identify endpoints that should be protected but are not.

Bearer Tokens-Specific Remediation in Django

Remediation focuses on strict token validation, minimizing data in responses, and hardening logging and transport settings. Below are concrete patterns you can apply in Django and Django REST Framework projects.

1. Use DRF’s TokenAuthentication with explicit permission classes

Ensure that views requiring authentication explicitly declare permission classes and that token validation is enforced. Avoid allowing unsafe methods for anonymous users.

from rest_framework.permissions import IsAuthenticated
from rest_framework.authentication import TokenAuthentication
from rest_framework.views import APIView
from rest_framework.response import Response

class UserProfileView(APIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request):
        # Only authenticated requests with a valid token reach here
        return Response({
            'id': request.user.id,
            'username': request.user.username,
            # Never include tokens or passwords in the response
        })

2. Customize token scope and validate audience

If you use a custom token model, add scope validation to ensure a token is only valid for intended endpoints. This prevents token reuse across services.

from rest_framework_simplejwt.tokens import Token

class CustomToken(Token):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Example: embed scope claim
        self.payload['scope'] = 'api:read'

def validate_token_scope(token, required_scope):
    scope = token.payload.get('scope')
    if scope != required_scope:
        raise PermissionDenied('Invalid token scope')
    return True

3. Serialize with explicit fields and exclude sensitive data

Define serializers that list only necessary fields. Avoid using fields = '__all__' when user data is exposed.

from rest_framework import serializers
from django.contrib.auth import get_user_model

User = get_user_model()

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'username', 'email']  # Explicitly declare safe fields
        # Exclude fields like 'password' or 'auth_token' automatically

4. Redact tokens in logging configuration

Update your logging configuration to filter out tokens from log messages. Use a custom filter to prevent accidental exposure.

import logging

class TokenFilter(logging.Filter):
    def filter(self, record):
        if hasattr(record, 'msg'):
            # Basic redaction pattern for bearer tokens in log messages
            if isinstance(record.msg, str) and 'Bearer ' in record.msg:
                record.msg = '[REDACTED]' 
        return True

logger = logging.getLogger()
logger.addFilter(TokenFilter())

5. Enforce HTTPS and secure headers

Set security headers and enforce HTTPS to prevent token interception in transit. Use Django middleware and settings to control transport security.

SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True

SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

6. Validate token origin and implement revocation

Where applicable, validate token origin and maintain a revocation list. Combine short-lived access tokens with refresh tokens to limit exposure if a token is compromised.

# Example of checking a token against a denylist (pseudocode)
from django.core.cache import cache

def is_token_revoked(token_jti):
    return cache.get(f'token_revoked_{token_jti}', False)

Related CWEs: dataExposure

CWE IDNameSeverity
CWE-200Exposure of Sensitive Information HIGH
CWE-209Error Information Disclosure MEDIUM
CWE-213Exposure of Sensitive Information Due to Incompatible Policies HIGH
CWE-215Insertion of Sensitive Information Into Debugging Code MEDIUM
CWE-312Cleartext Storage of Sensitive Information HIGH
CWE-359Exposure of Private Personal Information (PII) HIGH
CWE-522Insufficiently Protected Credentials CRITICAL
CWE-532Insertion of Sensitive Information into Log File MEDIUM
CWE-538Insertion of Sensitive Information into Externally-Accessible File HIGH
CWE-540Inclusion of Sensitive Information in Source Code HIGH

Frequently Asked Questions

How does middleBrick detect data exposure in Django APIs?
middleBrick runs unauthenticated scans combining OpenAPI/Swagger spec analysis with runtime checks. It examines response schemas for sensitive fields, verifies that authentication requirements are properly declared, and checks for missing security headers or overly permissive CORS configurations. No credentials are required; the scanner focuses on the public attack surface.
Can Bearer tokens be safely logged in Django development environments?
No. Tokens should never appear in logs, even in development. Use token redaction filters in your logging configuration and ensure that debug outputs do not include Authorization headers. Treat logs as potentially accessible and minimize sensitive data retention.