Opened 4 weeks ago

Closed 3 weeks ago

#37279 closed Bug (fixed)

URLValidator accepts null characters in URLs

Reported by: Nguyễn Anh Bình Owned by: Nguyễn Anh Bình
Component: Core (Other) Version: dev
Severity: Normal Keywords: not-security
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

URLValidator rejects tab and newline characters (via unsafe_chars = frozenset("\t\r\n"), added in #32713) but not the null character (\x00).

Example (Django 6.2.dev):

>>> from django.core.validators import URLValidator
>>> URLValidator()("http://www.djangoproject.com/\x00")  # no newline/tab, contains \x00
>>> URLValidator()("http://example.com/page\x00@example.com/")

Neither call raises ValidationError.

This is inconsistent with the rest of Django's input handling:

  • forms.CharField (and therefore forms.URLField) rejects \x00 via ProhibitNullCharactersValidator (#28201), so the same value submitted through a form is rejected.
  • Model-level URLField only applies URLValidator(), so values that reach Model.full_clean() through non-form paths (data imports, management commands, direct ORM writes from other systems) validate successfully while the identical value would fail any Django form.
  • ProhibitNullCharactersValidator exists precisely because NUL cannot appear in a valid URL and causes failures in downstream components (e.g. most databases reject or truncate it; PostgreSQL raises "A string literal cannot contain NUL (0x00) characters").

Null characters are invalid in URLs per RFC 3986 (excluded from every grammar production, ASCII control characters must be percent-encoded).

Proposed fix, mirroring the #32713 approach:

--- a/django/core/validators.py
+++ b/django/core/validators.py
@@ class URLValidator(RegexValidator):
-    unsafe_chars = frozenset("\t\r\n")
+    unsafe_chars = frozenset("\t\r\n\x00")

Happy to submit a PR with tests.

(Initially reported to security@…; the team classified it as non-security since form-based flows already reject NUL, and suggested the public tracker for the consistency hardening.)

Change History (6)

comment:1 by Nguyễn Anh Bình, 4 weeks ago

PR with the proposed fix and tests: https://github.com/django/django/pull/21787

(The PR was closed by the automation because this ticket is not yet Accepted; it will be re-submitted once the ticket is triaged.)

comment:2 by Jacob Walls, 3 weeks ago

Keywords: not-security added

comment:3 by Sarah Boyce, 3 weeks ago

Triage Stage: UnreviewedAccepted

comment:4 by Sarah Boyce, 3 weeks ago

Owner: set to Nguyễn Anh Bình
Status: newassigned

comment:5 by Sarah Boyce, 3 weeks ago

Triage Stage: AcceptedReady for checkin

comment:6 by Sarah Boyce <42296566+sarahboyce@…>, 3 weeks ago

Resolution: fixed
Status: assignedclosed

In c72f5fb4:

Fixed #37279 -- Rejected null characters in URLValidator.

Note: See TracTickets for help on using tickets.
Back to Top