AI Security Summary
Django's dominant attack surface spans its ORM query layer, template processing pipeline, and HTTP parsing stack. The recurring coding mistake is trusting user-controlled strings as structural query arguments or passing unbounded input to regex, HTML, and Unicode normalization routines without size or content guards.
ORM SQL Injection via Crafted Query Arguments and Column Aliases
Covers: CVE-2024-42005 · CVE-2025-64459 · CVE-2024-53908 · CVE-2025-57833 · CVE-2025-59681 · CVE-2025-13372 · CVE-2026-1207 · CVE-2026-1287 · CVE-2026-1312 Risk: Attacker-controlled dictionary keys or JSON object keys passed with ** expansion into QuerySet methods inject raw SQL through column aliases, connector arguments, or lookup parameters.
- NEVER pass user-supplied dictionary keys directly as **kwargs to QuerySet methods such as annotate(), alias(), aggregate(), values(), values_list(), filter(), exclude(), or get().
- NEVER use user-controlled strings as column aliases, connector arguments, or JSON field keys in ORM queries without an explicit allowlist of safe identifiers.
- ALWAYS sanitize and validate the structure of any dictionary before expanding it into ORM query methods, treating all keys as untrusted input.
- NEVER expose FilteredRelation, Q() connectors, or HasKey lookup parameters directly to request data without strict server-side validation of the input shape.
- ALWAYS use parameterized query helpers and ORM abstractions rather than constructing raw SQL fragments from user input, even indirectly via keyword argument expansion.
ReDoS and Algorithmic Complexity via Unbounded User Input to Validators and Template Filters
Covers: CVE-2023-36053 · CVE-2023-43665 · CVE-2024-38875 · CVE-2024-39614 · CVE-2024-41990 · CVE-2024-41991 · CVE-2024-53907 · CVE-2024-27351 · CVE-2025-32873 · CVE-2023-41164 · CVE-2025-26699 · CVE-2026-42310 Risk: Specially crafted long strings or malformed HTML/URL/Unicode input trigger catastrophic regex backtracking or O(n²) processing in validators, template filters, and text utilities, causing CPU exhaustion.
- NEVER pass raw user input of unbounded length to EmailValidator, URLValidator, truncatechars_html, truncatewords_html, strip_tags, urlize, urlizetrunc, intcomma, wordwrap, uri_to_iri, or get_supported_language_variant() without enforcing a hard character-count limit upstream.
- ALWAYS enforce a maximum input length at the request boundary before user data reaches any regex-backed validator or HTML-processing template filter.
- NEVER render attacker-controlled HTML fragments through Django template filters that traverse or parse HTML structure, as malformed tags can trigger non-linear processing time.
- ALWAYS treat very long inputs containing many dots, Unicode characters, or repeated partial HTML tags as a denial-of-service signal and reject them before processing.
HTTP Request Parsing Resource Exhaustion and Header Spoofing
Covers: CVE-2023-23969 · CVE-2023-24580 · CVE-2023-46695 · CVE-2024-24680 · CVE-2024-56374 · CVE-2025-27556 · CVE-2025-64458 · CVE-2026-25673 · CVE-2026-33034 · CVE-2026-3902 · CVE-2026-33033 · CVE-2026-5766 · CVE-2025-64460 Risk: Remote attackers exhaust server memory or CPU by sending oversized Accept-Language headers, excessive multipart parts, unbounded ASGI body reads, or Unicode-heavy inputs that trigger slow NFKC normalization, and can spoof headers via hyphen/underscore conflation in ASGI.
- NEVER trust the Content-Length header alone as a bound for request body reads in ASGI handlers; always enforce DATA_UPLOAD_MAX_MEMORY_SIZE and FILE_UPLOAD_MAX_MEMORY_SIZE at the application layer regardless of stated header values.
- ALWAYS set web-server-level limits on header size, number of multipart parts, and Content-Transfer-Encoding payload size before requests reach Django middleware.
- NEVER treat HTTP headers containing underscores as equivalent to their hyphen variants in ASGI request processing without explicit deduplication and conflict resolution.
- ALWAYS bound the length of Accept-Language, IPv6 address, URL, and username inputs before passing them to normalization or parsing functions, especially on Windows where NFKC normalization is disproportionately slow.
- NEVER pass untrusted XML to the Django XML deserializer without first enforcing a maximum depth and text-node size limit to prevent getInnerText() complexity attacks.
File Upload Validation Bypass and Path Traversal
Covers: CVE-2023-31047 · CVE-2024-39330 Risk: Attackers bypass file validation by uploading multiple files through a single FileField, or exploit custom Storage subclasses that omit parent-class path sanitization to achieve directory traversal.
- NEVER rely on a single forms.FileField or forms.ImageField to validate multiple simultaneously uploaded files; validate each file object individually and explicitly reject multi-file submissions on single-file fields.
- ALWAYS call the parent class generate_filename() validation logic when overriding it in a custom Storage subclass, or re-implement all path traversal checks from the base class.
- NEVER construct file save paths from user-supplied filenames without normalizing and validating the resulting path against the intended storage root.
- ALWAYS reject file uploads whose names contain path separators, null bytes, or directory traversal sequences before any storage operation.
Memory Corruption, Buffer Overflow, and Arbitrary Code Execution in Image Processing
Covers: CVE-2023-50447 · CVE-2023-4863 · CVE-2023-44271 · CVE-2024-28219 · CVE-2025-48379 · CVE-2026-25990 · CVE-2026-42311 · CVE-2026-42308 · CVE-2026-42309 · CVE-2026-40192 · CVE-2024-39329 · CVE-2024-45230 · CVE-2024-45231 · CVE-2025-48432 Risk: ACTIVELY EXPLOITED: Processing attacker-supplied images (WebP, PSD, DDS, FITS, fonts) or invoking PIL.ImageMath.eval with user input can cause heap buffer overflows, integer overflows, arbitrary code execution, or memory exhaustion; side-channel timing leaks also enable user enumeration.
- NEVER pass user-controlled strings or variables to PIL.ImageMath.eval() via the environment parameter, as this allows arbitrary code execution.
- ALWAYS validate image format, dimensions, and file size against strict allowlists before opening any user-supplied image with Pillow, and use the formats parameter to restrict accepted types.
- NEVER pass coordinate inputs from untrusted sources directly to Pillow drawing APIs such as ImagePath.Path, polygon(), or line() without validating that all coordinates are flat numeric pairs.
- ALWAYS sanitize request.path before including it in log output, and use constant-time comparison for authentication operations to prevent timing-based user enumeration.
- NEVER render user-supplied content through urlize() without escaping the output in contexts where HTML injection is possible.
- NEVER process FITS, PSD, or DDS images from untrusted sources without enforcing decompression size limits and validating tile extents before decoding.
Cross-cutting patterns (all Django projects)
- ALWAYS treat every value in a user-supplied dictionary as untrusted input before it touches the ORM, template engine, or file system, regardless of the calling convention.
- NEVER allow user input to determine the structural shape of a query, file path, or processing pipeline — only its scalar values within pre-validated parameters.
- ALWAYS enforce an explicit maximum byte length on every externally sourced string before it enters any validator, parser, serializer, or normalization function.
- NEVER process untrusted binary or structured file formats (images, XML, PDF, multipart) without sandboxing the parsing step and applying resource quotas on memory and CPU time.