Path Traversal in Django with Bearer Tokens
Path Traversal in Django with Bearer Tokens — how this specific combination creates or exposes the vulnerability
Path Traversal occurs when user-controlled input is used to access files outside the intended directory. In Django, this often involves file-serving views or document-management endpoints that build file paths using unsanitized input. When Bearer Tokens are used for authentication, developers may assume that because a request includes a token, the endpoint is safe from path manipulation. This assumption can be dangerous: authentication and authorization are separate from input validation. A Bearer Token may identify a user with permission to access a resource, but it does not guarantee that the requested file path is safe.
Consider an endpoint that serves user-uploaded documents. If the view uses a query parameter such as file_id to locate a file and constructs a filesystem path without proper sanitization, an attacker can supply sequences like ../../../etc/passwd. Even when a valid Bearer Token is provided, the token does not prevent the traversal; it only confirms who is making the request. Django’s default file handling does not automatically protect against directory traversal, and if the view uses Python’s open() or similar I/O directly, the application may expose sensitive files.
This combination is especially risky when the API also supports features such as OpenAPI/Swagger spec analysis, where runtime findings are cross-referenced with spec definitions. If a path traversal vulnerability exists in an endpoint that is documented in an OpenAPI spec, scanning can detect the unsafe path construction during unauthenticated attack surface testing. The scanner does not rely on the presence of a Bearer Token to identify the flaw; it probes endpoints with crafted paths to confirm whether traversal is possible. The presence of a Bearer Token changes the request identity but does not change the filesystem behavior if input validation is missing.
Real-world attack patterns include attempts to read configuration files, source code, or authentication artifacts. These map to OWASP API Top 10 categories and can align with findings from security scans that test unauthenticated and authenticated scenarios. In a CI/CD setup, using a GitHub Action can fail builds if risk scores degrade, but only if path traversal is flagged during testing. For continuous monitoring, the Pro plan’s checks include such scenarios across configurable schedules, helping teams detect regressions before deployment.
Bearer Tokens-Specific Remediation in Django — concrete code fixes
To secure Django endpoints that use Bearer Tokens, focus on strict input validation, safe path resolution, and avoiding direct filesystem access based on user input. Below are concrete code examples that demonstrate secure patterns.
Secure view with path validation and safe file serving
import os
from django.http import HttpResponse, Http404
from django.conf import settings
def serve_document(request, file_id):
# Assume Bearer Token authentication has already been verified
# and request.user is set via token validation middleware.
# file_id is a UUID or integer from a trusted database record.
try:
doc = Document.objects.get(id=file_id, owner=request.user)
except Document.DoesNotExist:
raise Http404("Document not found")
# Use a deterministic, safe path from the database, never from user input.
safe_path = doc.storage_path # e.g., 'uploads/uuid-filename.ext'
base_dir = settings.MEDIA_ROOT
full_path = os.path.join(base_dir, safe_path)
# Ensure the resolved path stays within the intended directory.
if not os.path.commonpath([os.path.realpath(full_path), os.path.realpath(base_dir)]) == os.path.realpath(base_dir):
raise Http404("Invalid path")
if os.path.isfile(full_path):
with open(full_path, 'rb') as f:
content = f.read()
return HttpResponse(content, content_type='application/octet-stream')
raise Http404("File not found")
Using Django’s FileResponse with validated paths
from django.http import FileResponse
from django.shortcuts import get_object_or_404
def stream_file(request, file_id):
user_file = get_object_or_404(UserFile, id=file_id, user=request.user)
# user_file.path should be a relative path stored during upload.
safe_path = user_file.path
file_path = os.path.join(settings.MEDIA_ROOT, safe_path)
return FileResponse(open(file_path, 'rb'), as_attachment=True, filename=user_file.name)
Token handling and authentication middleware
Ensure Bearer Tokens are validated using a robust library or custom middleware that sets request.user. Do not rely on tokens alone for path safety. Example token validation snippet:
import jwt
from django.http import HttpResponseForbidden
from django.utils.deprecation import MiddlewareMixin
class BearerTokenMiddleware(MiddlewareMixin):
def process_request(self, request):
auth_header = request.META.get('HTTP_AUTHORIZATION', '')
if auth_header.startswith('Bearer '):
token = auth_header.split(' ')[1]
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=['HS256'])
request.user = User.objects.get(id=payload['user_id'])
except (jwt.InvalidTokenError, User.DoesNotExist):
pass # Let the view handle unauthenticated requests
These patterns ensure that even when Bearer Tokens identify a user, file access is constrained by strict path resolution and ownership checks. They complement scanning tools that test for Path Traversal and help maintain secure API behavior across scans and deployments.
Related CWEs: inputValidation
| CWE ID | Name | Severity |
|---|---|---|
| CWE-20 | Improper Input Validation | HIGH |
| CWE-22 | Path Traversal | HIGH |
| CWE-74 | Injection | CRITICAL |
| CWE-77 | Command Injection | CRITICAL |
| CWE-78 | OS Command Injection | CRITICAL |
| CWE-79 | Cross-site Scripting (XSS) | HIGH |
| CWE-89 | SQL Injection | CRITICAL |
| CWE-90 | LDAP Injection | HIGH |
| CWE-91 | XML Injection | HIGH |
| CWE-94 | Code Injection | CRITICAL |