Skip to content

fix: tighten Django signed cookie identify_regex to cut false positives - #427

Merged
liquidsec merged 1 commit into
devfrom
fix/django-signedcookie-identify-fp
Jun 24, 2026
Merged

liquidsec merged 1 commit into
devfrom
fix/django-signedcookie-identify-fp

Conversation

@liquidsec

Copy link
Copy Markdown
Collaborator

Problem

DjangoSignedCookies.identify_regex matched any two colon-separated alphanumeric segments with no minimum length:

identify_regex = re.compile(r"^[\.a-zA-Z_\-0-9]+:[\.a-zA-Z_\-0-9:]+$")

This produced IdentifyOnly false positives on short values like abc:def, JSESSIONID:abcdef1234, and government app tokens such as 0000Qs-hTQlwlgXAYBlmgEFoQTR:1ffkg4vkm. Every other module in the library enforces minimum lengths (Rails {32,}--{16,}, Telerik {32,}, Express {20,90}); this one did not.

Fix

identify_regex = re.compile(r"^\.?[a-zA-Z0-9_-]+(?::[a-zA-Z0-9_-]{4,8})?:[a-zA-Z0-9_-]{27,}$")
  • ^\.? — optional leading dot (zlib-compressed payloads)
  • [a-zA-Z0-9_-]+ — base64url payload
  • (?::[a-zA-Z0-9_-]{4,8})? — optional base62 timestamp segment (TimestampSigner/dumps)
  • :[a-zA-Z0-9_-]{27,}$ — base64url HMAC signature (SHA-1 = 27 chars, SHA-256 = 43 chars)

Why this is complete (no old/new format split)

django.core.signing only ever emits two shapes, both :-separated: payload:signature (Signer) and payload:timestamp:signature (TimestampSigner/dumps). The only historical variation is the hash algorithm — SHA-1 (legacy, pre-3.1) → 27-char signature, SHA-256 (default since Django 3.1) → 43-char signature — both covered by {27,}. The middle segment is a base62 timestamp (6 chars this era; {4,8} has wide headroom), never a second signature. Verified by generating real cookies with the installed Django across Signer/TimestampSigner and both algorithms — all match.

Validation

Real Django cookies (all match): test-suite cookie, minimal TimestampSigner, minimal plain Signer, empty session dump, SHA-1 variants.

False positives (all rejected): 0000Qs-hTQlwlgXAYBlmgEFoQTR:1ffkg4vkm, abc:def, a:b, test:1234, JSESSIONID:abcdef1234, foo:bar:baz.

Tests

  • Added test_django_identify_false_positives to tests/django_signedcookies_test.py.
  • Existing tests/django_signedcookies_test.py and tests/carve_test.py pass unmodified (corrected a stale comment that mislabeled the timestamp segment).
  • uv run pytest tests/django_signedcookies_test.py tests/carve_test.py → 27 passed.

The identify_regex matched any two colon-separated alphanumeric segments
with no minimum length, producing IdentifyOnly false positives on short
values like abc:def, JSESSIONID:abcdef1234, and government app tokens
(0000Qs-hTQlwlgXAYBlmgEFoQTR:1ffkg4vkm).

Real django.core.signing output is always payload[:timestamp]:signature
where the signature is a base64url HMAC of at least 27 chars (SHA-1, 27)
or 43 chars (SHA-256, the default since Django 3.1). Anchor the regex to
that structure: optional leading dot, base64url payload, optional 4-8 char
base62 timestamp, and a 27+ char signature.

Verified against real cookies from both Signer/TimestampSigner and SHA-1/
SHA-256 algorithms; all match, while the false positives are rejected.
@liquidsec
liquidsec merged commit f5b67ea into dev Jun 24, 2026
4 of 8 checks passed
@liquidsec liquidsec mentioned this pull request Jun 24, 2026
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.45%. Comparing base (f14e50d) to head (8b5765f).
⚠️ Report is 28 commits behind head on dev.

Additional details and impacted files
@@           Coverage Diff           @@
##              dev     #427   +/-   ##
=======================================
  Coverage   99.45%   99.45%           
=======================================
  Files          30       30           
  Lines        3102     3102           
=======================================
  Hits         3085     3085           
  Misses         17       17           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants