CVE-2026-71502 Overview
CVE-2026-71502 is a stored cross-site scripting (XSS) vulnerability [CWE-79] in CTI-Transmute, a component of the MISP ecosystem. The flaw stems from insufficient neutralization of Vue template expression delimiters in server-rendered user-controlled data. An unauthenticated attacker can create a public conversion whose name or description contains a malicious Vue expression using the application's configured [[ ... ]] delimiters. User profile names offer an additional injection vector. Although Jinja applies HTML escaping, the escaped value is subsequently included in a DOM region compiled by Vue, which then evaluates the attacker-controlled payload as a template expression.
Critical Impact
Attackers can execute arbitrary JavaScript in the CTI-Transmute origin, hijack sessions, exfiltrate API keys, and target administrators to escalate impact.
Affected Products
- MISP CTI-Transmute (website component)
- Public conversion detail pages rendering conversion.name and description fields
- Public user profile pages rendering first and last name fields
Discovery Timeline
- 2026-08-08 - CVE-2026-71502 published to NVD
- 2026-08-08 - Last updated in NVD database
Technical Details for CVE-2026-71502
Vulnerability Analysis
CTI-Transmute serves pages through Jinja templates that mount a Vue application on the <main> region. Vue is configured with custom [[ ... ]] delimiters. When an attacker submits a public conversion name, description, or profile name containing those delimiters, Jinja HTML-escapes the string but leaves the delimiter characters intact. Vue then parses the rendered DOM subtree and treats the attacker's content as a template expression, invoking the JavaScript engine at compile time.
Because the application ships a nonce-based Content Security Policy (CSP), operators may expect script injection to be blocked. The Vue runtime compiler requires the unsafe-eval CSP exception, which nullifies the CSP defense against this class of payload. Any authenticated or anonymous visitor to an affected page triggers execution in the application origin.
Root Cause
The root cause is a layering conflict: Jinja escaping neutralizes HTML metacharacters but not Vue expression delimiters. Server-rendered values reach a client-side template compiler that treats them as executable syntax. This is a classic template-in-template injection where the output encoder of one engine is insufficient for the interpreter of another.
Attack Vector
An unauthenticated attacker creates a public conversion and stores a payload such as [[ [].constructor.constructor('...')() ]] in the name or description. The payload persists in the database. When another user, including an administrator, opens the public conversion detail page, Vue compiles the injected expression and executes arbitrary JavaScript. A short first-stage payload can fetch an uncapped conversion description and evaluate a larger second-stage payload, defeating any input-length limits.
// Patch example: applying v-pre to prevent Vue from compiling untrusted values
<h3 v-pre class="mb-1 text-truncate" style="font-weight:700; letter-spacing:-0.02em;">
{{ conversion_obj.name }}
</h3>
Source: MISP/cti-transmute commit 4f43c918
Detection Methods for CVE-2026-71502
Indicators of Compromise
- Stored conversion names, descriptions, or user profile fields containing the literal Vue delimiter sequences [[ and ]].
- Requests to /conversions/ or public profile endpoints containing constructor.constructor or [].constructor substrings.
- Anomalous outbound requests from browsers viewing public conversion detail pages, indicating token or API key exfiltration.
Detection Strategies
- Inspect database records for user-controlled string fields (conversion.name, conversion.description, profile_user.first_name, profile_user.last_name) matching the regex \[\[.+?\]\].
- Deploy a web application firewall rule to flag POST bodies to conversion creation and registration endpoints containing double square brackets alongside JavaScript identifiers such as constructor, Function, or fetch.
- Correlate browser console errors from client telemetry with page loads of public conversion or profile URLs.
Monitoring Recommendations
- Log and alert on new public conversions with unusually short names combined with non-alphanumeric delimiter characters.
- Monitor administrator sessions for unexpected authenticated API calls originating from the CTI-Transmute origin.
- Track CSP violation reports; absence of violations combined with observed exfiltration indicates the unsafe-eval path.
How to Mitigate CVE-2026-71502
Immediate Actions Required
- Apply the upstream patches from the MISP/cti-transmute repository that add a global Jinja finalize hook inserting a zero-width word joiner inside every Vue delimiter in server-rendered values.
- Audit and sanitize existing conversion names, descriptions, and profile names for stored [[ ... ]] payloads before restoring public access.
- Rotate any API keys, session tokens, or credentials exposed to pages rendered while the vulnerability was live.
Patch Information
The upstream fix is distributed across multiple commits. It adds v-pre to Jinja templates on the conversion detail, comparison, public profile, account index, register, and base flash-message regions so that Vue does not compile server-rendered user data. A global Jinja finalize hook additionally neutralizes any residual delimiters. Relevant commits: 4f43c918, 522fa8ff, ad8bf2b8, and ecfdaef6.
Workarounds
- Add v-pre directives to Jinja template blocks that render user-supplied strings inside the Vue-mounted <main> container.
- Reconfigure Vue to use pre-compiled render functions and remove the unsafe-eval CSP exception, eliminating the runtime template compiler.
- Restrict public conversion creation to authenticated users while the patch is validated in production.
# Example: server-side sanitization inserting a zero-width word joiner (U+2060)
# between Vue delimiter characters before rendering into Jinja templates
python -c "import re,sys; s=sys.stdin.read(); print(re.sub(r'(\[\[|\]\])', lambda m: m.group(0)[0]+'\\u2060'+m.group(0)[1], s))"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

