CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-9395-2G46-RJ3F

GHSA-9395-2G46-RJ3F: Multiple Cross-Site Scripting (XSS) Vulnerabilities in djust Template and Live Engine

Alon Barad
Alon Barad
Software Engineer

Sep 18, 2026·10 min read·4 visits

Executive Summary (TL;DR)

djust versions 1.0.0 through 1.1.0 contain multiple high-severity XSS vectors due to improper escaping in filters, slot rendering, and stateful WebSockets. Upgrading to 1.1.1 is required to secure affected applications.

A comprehensive technical analysis of six Cross-Site Scripting (XSS) vulnerability classes in the djust framework versions 1.0.0 through 1.1.0, involving escaping failures across the Python-Rust template boundary and stateful WebSocket cache lifecycles.

Vulnerability Overview

The stateful reactive web framework djust exposes a multi-tier architecture to deliver high-performance user interfaces without client-side compilation steps. This framework utilizes a Python application layer paired with a high-performance Rust-based virtual Document Object Model (VDOM) engine, distributed via the djust_templates and djust_live components. The attack surface of this hybrid system primarily exists along the serialization and state-synchronization boundaries, where data is passed between Python and Rust over active WebSocket channels.

Security advisory GHSA-9395-2G46-RJ3F documents six distinct classes of template and stateful view defects that result in Cross-Site Scripting (XSS). These vulnerabilities allow attackers to bypass standard auto-escaping controls because the rendering engine fails to sanitize inputs before translating them into the final Document Object Model. The security flaws encompass standard template filters, real-time WebSocket state management routines, and component slot rendering logic, presenting a wide range of injection opportunities.

Because the framework is designed to run reactive components dynamically, these template-layer defects bypass security assumptions without requiring developers to explicitly invoke dangerous functions. In several scenarios, standard usage of default filters like unordered_list and safeseq disables the auto-escaping mechanism entirely when encountering scalar inputs instead of sequences. This behavior allows any untrusted input stored in database records or request contexts to execute arbitrary JavaScript in user browsers, elevating the risk of application compromise.

The scope of these vulnerabilities spans all deployments of djust from version 1.0.0 through version 1.1.0 inclusive. Due to the high reachability of the affected filters and stateful components, organizations utilizing djust for interactive user dashboards must implement swift remediation. The lack of an assigned CVE identifier does not reduce the severity of the flaw, as demonstrated by the regression tests included in the framework's official codebase.

Root Cause Analysis

A deep analysis of the six vulnerability classes reveals three underlying architectural weaknesses: type-confusion in Rust filter logic, session state synchronization staleness, and unescaped return paths in Python slot handlers. In the filter-based vulnerabilities (V1), the Rust template library djust_templates maintains a static list of safe filters, SAFE_OUTPUT_FILTERS, which bypasses the renderer's standard auto-escaping. However, the filters unordered_list and safeseq did not handle scalar inputs securely; they returned non-sequence types verbatim, causing the template engine to emit unescaped HTML.

The state-synchronization vulnerability (V3) stems from the lifetime management of safety assertions over stateful WebSocket connections in crates/djust_live/src/lib.rs. When a component initially renders a variable marked safe using Django's mark_safe function, the RustLiveViewBackend records the variable's key inside a persistent safe_keys cache. Because this cache was never cleared or updated during subsequent state-change events over the active WebSocket, any update to that variable with hostile user input inherited the "safe" status. Consequently, the backend transmitted the malicious payload over the WebSocket connection without escaping, leading to persistent client-side script execution.

The remaining flaws (V2, V4, V5, V6) represent escaping failures under specific template combinations. For instance, the slot rendering tag {% render_slot %} processed scalar values through an execution path that directly emitted the context value without escaping. For filters like escape and linenumbers, the engine relied on the late-stage auto-escaping of the template engine, which failed when developers appended the |safe filter to the chain. Furthermore, filters such as linebreaks and linebreaksbr escaped their own generated markup, forcing developers to use |safe to render page elements correctly, which in turn exposed user inputs directly to the browser.

These design flaws show a systemic failure to implement a fail-closed escaping model. The system frequently assumed that escaping duties would be handled by adjacent components or later stages of the rendering pipeline. By omitting structural checks at the immediate boundary where data is transformed or updated, the framework created multiple execution paths where untrusted strings reached the client's browser unmodified.

Code Analysis

The patch introduced in version 1.1.1 restructures the escaping logic to use a fail-closed architecture, validating types and revoking stale safety grants dynamically. In crates/djust_live/src/lib.rs, the stateful WebSocket backend now explicitly monitors updates to the state dictionary and purges matching safety keys. When a key is modified, its existing safe-status registration is revoked alongside any nested keys, preventing hostile overrides from inheriting trusted privileges:

// In crates/djust_live/src/lib.rs - State update handler
fn update_state(&mut self, updates: HashMap<String, Value>) {
    // If our safe_keys cache contains records, we must clean them up
    if !self.safe_keys.is_empty() {
        for key in updates.keys() {
            // Revoke the exact key's safety flag to prevent stale grants (#2300)
            self.safe_keys.remove(key);
            let prefix = format!("{key}.");
            // Also revoke safety flags for all sub-properties (e.g., 'p.field')
            self.safe_keys.retain(|k| !k.starts_with(&prefix));
        }
    }
    // Perform the standard state merge
    self.state.extend(updates);
}

In crates/djust_templates/src/filters.rs, the engine was modified to prevent escaping bypasses caused by appending |safe to self-escaping filters. The framework introduced a self_escaping flag that is returned by the filter dispatcher. When a filter like escape, linenumbers, or linebreaks is executed, the dispatcher marks the output as self_escaping, preventing the rendering engine from double-escaping while neutralizing any trailing |safe directives:

// In crates/djust_templates/src/filters.rs - Filter dispatch routine
pub fn apply_filter_full_safe(
    filter_name: &str,
    value: &Value,
    arg: Option<&Value>,
    context: &Value,
    arg_was_quoted: bool,
) -> Result<(Value, bool)> {
    if let Some(builtin) = apply_builtin_filter(filter_name, value, arg, context) {
        // These built-ins perform internal HTML escaping and flag their outputs
        // to prevent double-escaping or bypasses via subsequent '|safe' filters (#2281)
        let self_escaping = matches!(
            filter_name,
            "escape" | "linenumbers" | "linebreaks" | "linebreaksbr"
        );
        return builtin.map(|v| (v, self_escaping));
    }
    // ...
}

To address the type-confusion vulnerabilities in scalar fallbacks (V1), the filters safeseq and unordered_list were updated to explicitly escape scalar strings before returning them. Previously, if these filters encountered a string instead of a sequence, they returned it directly without modification, skipping the rendering engine's auto-escape logic. The patched code forces scalar values through the html_escape utility:

// In crates/djust_templates/src/filters.rs - Scalar fallback implementations
"safeseq" => {
    match value {
        Value::List(_) => Ok(value.clone()),
        // Escapes scalar values immediately to prevent unescaped output (#2283)
        _ => Ok(Value::String(html_escape(&value.to_string()))),
    } 
}
"unordered_list" => {
    match value {
        Value::List(items) => Ok(Value::String(unordered_list(items, 1))),
        // Scalar values are now escaped, blocking raw HTML injection
        _ => Ok(Value::String(html_escape(&value.to_string()))),
    }
}

Additionally, Python component rendering in python/djust/components/function_component.py was patched to strictly sanitize scalar values returned from custom slot tags. The updated logic calls Django's html.escape on pre-resolved scalar outcomes and fallback strings. This correction prevents the engine from inserting unescaped tag values directly into the DOM stream, ensuring a comprehensive security posture across both language boundaries.

Exploitation & Attack Methodology

Exploiting these vulnerabilities requires targeting an application endpoint that accepts user input and renders it within a vulnerable template context or WebSocket live-view. An attacker can construct a payload containing standard HTML tags and JavaScript event handlers, such as <img src=x onerror=alert(1)>. If an application uses the unordered_list filter to display dynamic attributes, submitting this payload triggers the V1 vulnerability because the filter returns the scalar payload unchanged and suppresses late-stage auto-escaping.

To exploit the state persistence vulnerability (V3), the attacker leverages the stateful nature of WebSocket connections. An application view must contain a template variable that is initially populated with a trusted, server-defined string marked safe via mark_safe. Once the WebSocket connection is established and the rendering engine caches the variable's key as safe, the attacker triggers an application event that updates the same variable with a hostile string. Because the backend does not clear the safe-keys cache, the malicious input is transmitted to the client and rendered without escaping.

In scenarios involving component slots (V2), exploitation is even more direct. If a developer implements a layout template that renders slots using {% render_slot p %}, where p is a dynamic context variable, the attacker can supply the payload directly to p. Because the Python engine did not escape pre-resolved scalars in version 1.1.0, the payload is written directly to the DOM stream. This mechanism requires no special developer configurations or custom tags to achieve complete cross-site scripting.

The logical progression of a stateful WebSocket exploit is modeled below. It traces the state synchronization and the subsequent security bypass that occurs when the caching layer fails to invalidate stale keys.

Impact Assessment

The impact of these Cross-Site Scripting vulnerabilities within djust is high due to the framework's use case in high-frequency, real-time web applications. If an administrative panel or interactive portal uses djust to display real-time feeds, an attacker can exploit these flaws to execute arbitrary JavaScript in the context of an administrator's browser session. This execution capability allows the attacker to steal session identifiers, hijack active WebSocket channels, and perform unauthorized operations.

The CVSS v3.1 vector for this set of vulnerabilities is evaluated as CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N, resulting in a high score. The attack vector is network-based and does not require specialized privileges, meaning any unauthenticated visitor can target vulnerable input fields. The security scope is changed because the compromise of the server's templating output leads to a complete breakdown of security boundaries within the client's browser sandbox.

Although there are no reports of active exploitation in the wild, the presence of functional test-case reproducers within the public repository reduces the effort required to weaponize these vectors. The test suite contains clear code paths to trigger the V1, V2, V3, and V4 vulnerabilities. Consequently, organizations must assume that threat actors can quickly analyze the repository differences to develop working exploits against target installations.

Furthermore, because the state updates are sent over WebSockets as JSON payloads, traditional security monitors often fail to inspect these data streams. The lack of standard HTTP boundaries for individual component updates means that simple signature matching on typical HTTP POST requests will not detect exploits delivered over an active WebSocket session. This detection gap increases the operational impact by allowing attacks to bypass standard firewall boundaries.

Remediation & Defensive Guidance

The direct and recommended remediation is to upgrade the djust dependency to version 1.1.1 or higher immediately. This version contains complete backports for all six vulnerability classes, introducing type-safe scalar escaping, state cache clearing, and self-escaping template filters. To implement this fix, developers should update their application's dependency management files, such as requirements.txt or pyproject.toml, to enforce the use of djust>=1.1.1.

If an immediate upgrade is not feasible, temporary code-level mitigations should be applied to minimize the attack surface. Developers must audit all templates to identify usages of the vulnerable filters unordered_list, safeseq, linenumbers, linebreaks, and linebreaksbr. For any instance where these filters process untrusted data, the code should be rewritten to perform manual HTML escaping within a standard loop, avoiding the use of the flawed built-in filters.

Additionally, applications must restrict the use of component slots that handle user-supplied variables. In template blocks containing {% render_slot %}, ensure that the variable passed to the slot is strictly validated and sanitized before rendering. If the variable contains user text, pass it through an explicit escaping utility in the Python controller prior to sending it to the rendering pipeline, bypassing the vulnerable raw-string fallback path.

To implement defense-in-depth, security teams should configure a strict Content Security Policy (CSP) on the web server. The CSP should include a restrictive script-src directive that forbids inline scripts and enforces the use of cryptographic nonces or specific source domains. This configuration ensures that even if an attacker successfully injects HTML markup through a template flaw, the browser will refuse to execute the injected JavaScript payloads, neutralizing the impact of the exploit.

Official Patches

djust-orgOfficial patch file containing fixes for the template escaping issues

Technical Appendix

CVSS Score
8.2/ 10

Affected Systems

djust application deploymentsdjust template engine (djust_templates)djust live-view backend (djust_live)

Affected Versions Detail

Product
Affected Versions
Fixed Version
djust
djust-org
>= 1.0.0, <= 1.1.01.1.1
AttributeDetail
CWE IDCWE-79
Vulnerability ClassImproper Neutralization of Input During Web Page Generation (Cross-Site Scripting)
Attack VectorNetwork (AV:N)
Attack ComplexityLow (AC:L)
Privileges RequiredNone (PR:N)
User InteractionRequired (UI:R)
ScopeChanged (S:C)
Exploit StatusFunctional Proof-of-Concept (PoC) available

MITRE ATT&CK Mapping

T1059Command and Scripting Interpreter
Execution
T1189Drive-by Compromise
Initial Access

Vulnerability Timeline

Vulnerability patched and version 1.1.1 released
2026-08-29

References & Sources

  • [1]djust Main Repository
  • [2]GitHub Security Advisory GHSA-9395-2G46-RJ3F
  • [3]djust v1.1.1 Release Notes
  • [4]djust comparative diff v1.1.0 to v1.1.1

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•6 minutes ago•CVE-2026-77281
6.5

CVE-2026-77281: Rewrite Placeholder Re-expansion Vulnerability in Caddy Web Server

A critical double-evaluation vulnerability exists in the rewrite module of the Caddy web server. Under specific configurations where a rewrite directive ends with a literal question mark and processes client-controlled headers, the system performs a secondary expansion pass. This allows attackers to evaluate arbitrary internal placeholder variables, leading to unauthorized disclosure of sensitive environment variables and system files.

Amit Schendel
Amit Schendel
0 views•8 min read
•about 1 hour ago•CVE-2026-77615
8.7

CVE-2026-77615: Stored Cross-Site Scripting (XSS) in Paella Player as used in Opencast

CVE-2026-77615 is a high-severity Stored Cross-Site Scripting (XSS) vulnerability in the Paella Player component, which is integrated as the default front-end media viewer in Opencast. Unsafe client-side rendering of subtitle tracks allows authenticated, low-privileged users to inject arbitrary JavaScript payloads via crafted WebVTT or DFXP files. The script executes within the context of any viewer session under the host origin, enabling session hijacking and unauthorized API interaction.

Alon Barad
Alon Barad
1 views•5 min read
•about 3 hours ago•GHSA-XJW9-38CR-6372
8.2

GHSA-XJW9-38CR-6372: Cross-Site Scripting via Stale Safe-Key Inheritance in djust Template Shadowing

An escaping defect in the djust templating engine allows Cross-Site Scripting (XSS) when a template binding construct shadows a variable that was previously marked safe. The Rust-based context safety tracking incorrectly preserves name-based safety grants even after the variable name has been bound to a new, untrusted value.

Amit Schendel
Amit Schendel
5 views•6 min read
•about 4 hours ago•CVE-2026-81875
7.5

CVE-2026-81875: Unbounded DEFLATE Decompression Denial of Service in HAPI FHIR SHCParser

A critical denial of service vulnerability exists in the HAPI FHIR SHCParser within the org.hl7.fhir.core Java library. Unbounded decompression of raw DEFLATE data during Smart Health Card parsing allows unauthenticated remote attackers to trigger JVM heap exhaustion and crash the application.

Alon Barad
Alon Barad
5 views•7 min read
•about 5 hours ago•CVE-2026-81876
7.5

CVE-2026-81876: Unauthenticated Denial of Service via Infinite Loop in HAPI FHIR SHCParser

CVE-2026-81876 is a high-severity Denial of Service vulnerability in HAPI FHIR, a complete Java implementation of the HL7 FHIR standard. The vulnerability stems from improper usage of Java's java.util.zip.Inflater class within the Smart Health Card (SHC) parser.

Amit Schendel
Amit Schendel
6 views•6 min read
•about 6 hours ago•CVE-2026-82399
7.5

CVE-2026-82399: Resource Exhaustion Denial of Service in CoreDNS Custom Transports

CVE-2026-82399 is a resource management vulnerability in CoreDNS affecting custom DNS transport pathways. Prior to version 1.14.7, transports including DNS-over-HTTPS (DoH), DNS-over-QUIC (DoQ), and DNS-over-gRPC executed the resource-intensive unpack method of the underlying Go DNS library on raw, untrusted incoming payloads before validating the fixed 12-byte DNS header. An unauthenticated remote attacker can exploit this behavior by using nested DNS name compression pointers to trigger substantial heap allocations, leading to memory exhaustion and server termination.

Amit Schendel
Amit Schendel
5 views•7 min read