Sep 17, 2026·6 min read·50 visits
Unauthenticated XSS vulnerability in @nuxtjs/mdc prior to 0.22.1 allows attackers to bypass URL sanitizers and execute arbitrary scripts via crafted SVG xlink:href attributes and data:text/html URIs.
A cross-site scripting (XSS) vulnerability was identified in @nuxtjs/mdc prior to version 0.22.1. Gaps in the HTML/SVG attribute verification and URL protocol parsing allow unauthenticated remote attackers to bypass the application's sanitization routines. By embedding malicious SVG links or data-encoded iframe elements within Markdown, attackers can execute arbitrary JavaScript in the victim's browser context.
The @nuxtjs/mdc (Markdown Components) library is a core framework component within the Nuxt content ecosystem. It parses Markdown documents into a Hypertext Abstract Syntax Tree (HAST) and renders them as interactive Vue components. By design, this package supports rich content rendering, including raw HTML processing when configured with default parameters.
This analysis examines CVE-2026-63671, a critical cross-site scripting (XSS) vulnerability residing within the parsing utility layer of @nuxtjs/mdc prior to version 0.22.1. The vulnerability emerges from gaps in the attribute sanitization mechanism, which is designed to identify and neutralize malicious URIs.
The vulnerability allows remote, unauthenticated attackers to bypass default security filters by supplying crafted Markdown elements. Specifically, the sanitizer fails to intercept SVG-specific hyperlink attributes and misinterprets standard URL protocol definitions for data URIs. This results in the insertion of executable scripts directly into the DOM of the rendering web application.
The primary failure mechanism involves the sanitizer implementation found in src/runtime/parser/utils/props.ts. The implementation defines a validation gatekeeper via the validateProp function. This function restricts security checks to an explicit allowlist of properties, specifically looking for exact matches of href and src.
When the HAST parser processes Scalable Vector Graphics (SVG) structures, it translates XML attributes into standardized Javascript representations. The standard SVG attribute xlink:href is converted into camelCase or lowercase equivalents such as xLinkHref or xlinkhref. Because the pre-patch logic only verified href and src, the xlinkhref attribute bypassed validation entirely and passed raw javascript: payloads straight to the renderer.
The second logical error resides in the isAnchorLinkAllowed function, which determines whether a URI protocol is safe. The parser evaluated incoming strings using a denylist of protocols, checking if url.protocol starts with elements from unsafeLinkPrefix, which included data:text/html. However, standard Web API URL parsing rules resolve the protocol property of any data URI strictly to the string data:.
Consequently, executing url.protocol.startsWith('data:text/html') evaluated to false because 'data:' does not start with 'data:text/html'. This logic flaw allowed arbitrary data-encoded payload delivery using the data:text/html media type. The vulnerability constitutes an incomplete input validation weakness classified under CWE-184 and CWE-79.
The logic within src/runtime/parser/utils/props.ts can be analyzed to understand the precise mechanics of the security patch. The pre-patch validation structure relied on strict string equality checks against a limited subset of HTML attributes, leaving SVG specifications unprotected.
Below is a comparison highlighting the changes implemented in the official patch:
// PRE-PATCH IMPLEMENTATION
export const validateProp = (attribute: string, value: string) => {
if (attribute === 'href' || attribute === 'src') {
return isAnchorLinkAllowed(value)
}
}
function isAnchorLinkAllowed(value: string) {
// ...
if (unsafeLinkPrefix.some(prefix => url.protocol.toLowerCase().startsWith(prefix))) {
return false
}
// ...
}The remediation, introduced in commit 61d636c2983f021288e4fc5c4006733b38cf0d53, modified the validation scope and structural validation rules:
// POST-PATCH IMPLEMENTATION
export const validateProp = (attribute: string, value: string) => {
// Added explicit validation for 'xlinkhref' to cover SVG hyperlinks
if (attribute === 'href' || attribute === 'src' || attribute === 'xlinkhref') {
return isAnchorLinkAllowed(value)
}
}
function isAnchorLinkAllowed(value: string) {
// ...
// Changed verification from 'url.protocol' to the full serialized 'url.href'
if (unsafeLinkPrefix.some(prefix => url.href.toLowerCase().startsWith(prefix))) {
return false
}
// ...
}The patch replaces the protocol checking mechanism with a prefix match against the fully qualified URL string (url.href). This guarantees that string sequences matching data:text/html are correctly blocked. Additionally, explicit support for matching the xlinkhref attribute was introduced to cover the vulnerability in SVG elements.
Exploitation of CVE-2026-63671 requires feeding a malicious Markdown payload to the @nuxtjs/mdc parser. The parser must render the input inside an application context where HTML rendering is active.
The attack path is visualized below:
To execute the SVG vector, the attacker provides a nested SVG element inside the markdown payload. When parsed, this bypasses the standard href validation gate and places a dangerous link in the browser DOM.
<svg viewBox="0 0 10 10">
<a xlink:href="javascript:alert(document.domain)">click here</a>
</svg>Alternatively, the attacker can leverage the iframe vector to deliver an interactive payload that runs in a nested context. The validator processes the src attribute but fails to identify the data protocol bypass.
<iframe src="data:text/html,<script>alert(document.cookie)</script>"></iframe>The execution of arbitrary script content within the context of a victim session yields severe consequences. Because @nuxtjs/mdc renders content directly into the host Nuxt application, an injected script executes with the full privileges of the application origin.
Attackers can capture sensitive session variables, access local storage or session storage tokens, and hijack active application sessions. In environments handling authenticated transactions, this vulnerability permits unauthenticated state changes on behalf of the user.
The CVSS v3.1 score of 8.1 reflects a high threat profile. Since exploitation requires minimal user interaction and low complexity, automated exploits can be deployed via malicious markdown uploads or comment fields.
The primary mitigation step is updating @nuxtjs/mdc to version 0.22.1 or later. This upgrade addresses both the SVG attribute parsing gap and the data protocol verification failure.
Applications that cannot immediately deploy the dependency update should disable rendering of dangerous inline HTML. This can be achieved by setting the allowDangerousHtml option to false in the markdown parser configuration interface.
Furthermore, security teams should implement a Content Security Policy (CSP) to mitigate downstream impact. A robust CSP restricting script-src directives prevents the execution of inline scripts and unauthorized data URIs even if a sanitizer bypass occurs.
CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
@nuxtjs/mdc nuxt-content | < 0.22.1 | 0.22.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-79, CWE-184 |
| Attack Vector | Network |
| CVSS v3.1 Score | 8.1 |
| Exploit Status | poc |
| KEV Status | Not listed |
| Impact | Cross-Site Scripting (XSS) |
The product does not sanitize or incorrectly sanitizes user-controlled input before including it in output which is served as web content.
CVE-2026-118777 is a prototype pollution vulnerability (CWE-1321) in the Forge JavaScript cryptography and networking library (distributed on npm as node-forge) prior to version 1.4.1. The flaw resides in the forge.http client subsystem, where incoming HTTP cookie names and paths parsed from Set-Cookie response headers are stored directly into standard JavaScript objects without key validation or property isolation. By returning crafted Set-Cookie headers containing keys such as __proto__ or constructor, a malicious HTTP server can inject arbitrary properties into Object.prototype, attach attributes to the global Object constructor, or delete built-in prototype methods to cause an application-wide denial of service.
CVE-2026-118775 (GHSA-4642-5mcj-2rqw) is an integer overflow and validation flaw in the ASN.1 serialization module of Forge (node-forge) prior to version 1.4.1. The asn1.oidToDer() function fails to validate the range of the first two arcs of an Object Identifier (OID) and truncates the packed initial subidentifier to a single 8-bit integer. Applications that perform policy checks on untrusted OID strings before encoding them into Distinguished Encoding Rules (DER) format can be tricked into emitting DER bytes that correspond to a completely different, restricted OID.
CVE-2026-119194 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting versions 0.3.3 through 0.6.4. The flaw resides in the schemaless decoding routine ConstructedPayloadDecoderBase._decodeComponentsSchemaless used across BER, CER, and DER codecs. By sending an ASN.1 container populated with child components whose tag identifiers are separated by multiples of CPython's integer hash modulus (sys.hash_info.modulus), an unauthenticated attacker can force worst-case hash collisions in an unbounded Python set, degrading decoding performance from O(N) to O(N^2) and causing a Denial of Service (DoS).
CVE-2026-119195 is an algorithmic complexity vulnerability (CWE-407) in the pyasn1 library for Python, affecting all versions prior to 0.6.5. When decoding constructed strings or indefinite-length ANY types across BER, CER, and certain DER code paths, the payload decoders repeatedly concatenate incoming fragments onto an immutable bytes object using the += operator. Because Python bytes objects cannot be resized in-place, each fragment iteration allocates a new buffer and copies all previously accumulated bytes, resulting in quadratic O(N^2) time and memory copy complexity. An unauthenticated remote attacker can supply a highly fragmented ASN.1 stream to exhaust CPU cycles and stall application worker threads.
An algorithmic complexity vulnerability (CWE-407) in pyasn1 versions prior to 0.6.5 allows unauthenticated attackers to cause a Denial of Service (DoS) via crafted ASN.1 payloads. The flaw resides in the binary-encoded ASN.1 REAL mantissa deserialization routine within RealPayloadDecoder.valueDecoder. By performing iterative byte-string slicing and repeated bitwise shifts on a growing arbitrary-precision integer, the decoder exhibits quadratic time and memory allocation complexity relative to the mantissa length. Supplying a BER-, CER-, or DER-encoded payload with a large REAL mantissa causes excessive CPU consumption and blocks application worker processes.
A vulnerability classified under CWE-407 (Inefficient Algorithmic Complexity) exists in the pyasn1 library prior to version 0.6.5. When parsing constructed ASN.1 BIT STRING payloads under BER, CER, or schema-driven DER encoding rules, the BitStringPayloadDecoder repeatedly shifts and copies the entire accumulated bit value for each incoming fragment. Processing inputs with a large number of small constructed fragments induces quadratic CPU consumption, allowing unauthenticated remote attackers to cause a denial of service via resource exhaustion during the initial decoding phase.