Date: 2026-06-16 Target: Django 5.2.11 Truncator (patched CVE-2026-1285) Verdict: VULNERABLE-CONFIRMED (Medium DoS).
ACTUALLY APPLIED on the data path. Django's fix added MAX_LENGTH_HTML = 5_000_000 and a docstring saying
"input will be limited to at most MAX_LENGTH_HTML characters" - but the constant is referenced NOWHERE in the
code (defined + documented + never sliced). A documented mitigation that is dead code is an objective
incomplete fix you can prove with one grep. Checklist for any fix that introduces a limit/cap/flag:
grep -rn <CONST> -> is it READ on the vulnerable path, or only defined? Defined-only = gap.
was LIFO endtag handling (kills the deque.remove() O(n) scan). But a different O(n^2) survived: tag-heavy/
no-text input never trips the truncation early-exit, so the parser walks the whole input doing
self.output += ... - and STORE_ATTR += does NOT get CPython's in-place string-concat optimization that
STORE_FAST (locals) gets => O(n^2). When auditing an algorithmic-complexity fix, find an input class that
AVOIDS the early-exit the fix relies on (here: no text -> no truncation -> full traversal).
(linear=8x) is decisive even when the exact exponent is noisy (realloc/GC cliffs). Lead with "sub-MB -> multi-second CPU on a request-reachable filter", not a precise n^2 claim you cannot cleanly measure.
bundle SWEPT the alias-SQLi cluster (check_alias across annotate/aggregate/values/order_by/FilteredRelation/ extra) but POINT-FIXED the Truncator DoS (closed one quadratic, missed another, shipped a dead cap). Audit each bundled fix independently; a project that sweeps one class may point-fix another in the same release.
self.attr += str in a loop is O(n^2) (no in-place opt); local += str isamortized O(n). A security-relevant slow-path that accumulates into an attribute is a complexity-DoS smell.