PYSEC-2026-4037

See a problem?
Import Source
https://github.com/pypa/advisory-database/blob/main/vulns/djust/PYSEC-2026-4037.yaml
JSON Data
https://api.osv.dev/v1/vulns/PYSEC-2026-4037
Aliases
Published
2026-10-01T16:38:31Z
Modified
2026-10-01T17:45:03Z
Severity
  • 5.1 (Medium) CVSS_V4 - CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:P/VC:N/VI:N/VA:N/SC:L/SI:L/SA:N CVSS Calculator
Summary
djust is vulnerable to stored/reflected XSS via javascript: URLs in built-in component template tags
Details

Impact

Many djust built-in component template tags (djust.components.templatetags.*) render a developer/user-supplied URL into an href / action attribute, HTML-escaping it with conditional_escape but never validating the URL scheme. HTML escaping prevents attribute breakout but does not neutralize a javascript: URI (which needs no escapable characters), so a URL value of javascript:alert(document.cookie) lands verbatim in <a href="javascript:alert(document.cookie)"> and executes in the victim's session on click.

Affected sinks (executing href/action contexts; not exhaustive): breadcrumb (djust_components.py:1535; _advanced.py:1999,2022), dj_nav link/dropdown/brand (djust_components.py:5632,5779,5807,5830), citation URL (:6936), cookie-consent privacy link (:8240), error-page action (_advanced.py:1728), form action (_forms.py:1239). <img src> sinks are lower risk (javascript: does not execute via img src). No scheme validation exists anywhere in the component tags; a docstring at djust_components.py:781 even acknowledges the javascript: risk without mitigating it.

Severity Medium: XSS in the victim's authenticated session whenever an app renders one of these components with a URL sourced from user-controllable data; for href requires a click, worst case is the stored variant (URL persisted from one user, rendered to another). Conditional on developer usage, hence Medium rather than High.

Reproduced: breadcrumb(items=[{"label":"Home","url":"javascript:alert(document.cookie)"}]) emits <a ... href="javascript:alert(document.cookie)">Home</a>; JaVaScRiPt: case variant also passes; https:// URLs are preserved.

Patches

Add a safe_url() helper that neutralizes non-allowlisted schemes (javascript:, vbscript:, data:) to # while preserving http/https/mailto/tel/relative/anchor URLs, and route every href/action/formaction/xlink:href sink through it (then HTML-escape). Add a regression + an audit_ast/system-check rule flagging un-routed URL-attribute interpolation.

Workarounds

Do not pass user-controllable URLs to the affected built-in component tags; pre-validate URL schemes in application code before binding them to component arguments.

References

Reproducer + finding writeup retained privately by the maintainer.

References

Affected packages

PyPI / djust

Package

Affected ranges

Type
ECOSYSTEM
Events
Introduced
0 Unknown introduced version / All previous versions are affected
Fixed
1.0.7

Affected versions

0.*
0.1.0
0.1.2
0.1.3
0.1.4
0.1.5
0.1.6
0.1.7
0.1.8
0.1.9
0.2.0
0.2.1
0.2.2
0.3.0
0.3.1
0.3.2
0.3.4
0.3.5
0.3.6
0.3.7
0.3.8
0.4.0
0.4.1
0.4.2
0.4.3
0.4.4
0.9.0
0.9.1
0.9.2
0.9.4
0.9.5
0.9.6
0.9.7
1.*
1.0.0rc11
1.0.0
1.0.1
1.0.2
1.0.3
1.0.4
1.0.5
1.0.6

Database specific

source
"https://github.com/pypa/advisory-database/blob/main/vulns/djust/PYSEC-2026-4037.yaml"