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-M3Q2-P4FW-W38M

GHSA-M3Q2-P4FW-W38M: Cross-Site Scripting (XSS) via Unsafe innerHTML Assignment in Nuxt <NoScript> Component

Amit Schendel
Amit Schendel
Senior Security Researcher

Jun 17, 2026·8 min read·5 visits

Executive Summary (TL;DR)

Unsafe innerHTML assignment in Nuxt's <NoScript> component allows Cross-Site Scripting (XSS) when untrusted dynamic data is interpolated in slots. Historically significant as one of the first zero-days discovered and reported by an AI assistant (Claude).

A low-severity Cross-Site Scripting (XSS) vulnerability in Nuxt's globally registered <NoScript> head component allows unauthenticated attackers to execute arbitrary JavaScript. By injecting dynamic, untrusted data into <NoScript> slots, standard Vue HTML escaping is bypassed because the component processes slot text nodes and assigns them directly to the target element's innerHTML property instead of textContent. In modern browsers with scripting enabled, this raw injection can implicitly close the <noscript> tag, triggering script execution.

Vulnerability Overview

Nuxt is a high-performance, open-source web framework built on top of Vue.js, optimized for server-side rendering (SSR), static site generation (SSG), and single-page applications. Inside Nuxt applications, managing document head tags (such as title, meta, link, and style tags) is handled dynamically via head runtime components. These components are globally registered and managed by the underlying @unhead/vue engine, allowing developers to declaratively configure page metadata directly within their Vue templates. One such component is the <NoScript> component, designed to output a <noscript> tag that specifies fallback content for users who have disabled JavaScript in their browsers.

The attack surface of this vulnerability lies in the input pipeline of the <NoScript> runtime component. While typical Vue.js template interpolations automatically sanitize dynamic values by escaping HTML entities, the internal rendering logic of Nuxt's head components circumvents this mechanism. When developers render dynamic parameters, query values, or database-derived content directly within the slot of the <NoScript> component, the raw string is processed. Because the application exposes an interface where raw input is accepted and transferred to the server's output response without sanitization, it establishes a classic injection path.

This vulnerability is classified under CWE-79 (Improper Neutralization of Input During Web Page Generation). It occurs when user-supplied input is rendered directly into the Document Object Model (DOM) without undergoing appropriate sanitization or escaping. The ultimate impact of this flaw is Cross-Site Scripting (XSS), which enables attackers to execute arbitrary JavaScript within the security context of the victim's session. Although classified with a low severity rating of 2.3 due to the specific conditions required to trigger it, the weakness exposes applications to session hijacking, credential harvesting, and DOM manipulation.

Root Cause Analysis

To understand the root cause of this vulnerability, one must analyze how Vue compiles slot children and how Nuxt aggregates them. When a developer writes a <NoScript> element containing a dynamic expression, the Vue compiler compiles the slot contents as a Virtual DOM text node. The Nuxt <NoScript> runtime component, located in packages/nuxt/src/head/runtime/components.ts, reads these slot text nodes to construct the final output. The component extracts the content from the children array and inserts it into a local array named textContent.

The critical vulnerability is introduced when the component updates the target noscript DOM element. Instead of assigning the aggregated plain text to a safe DOM property like textContent or innerText, the component logic executes an assignment directly to the innerHTML property. This function call instructs the browser's DOM parser to interpret the assigned string as active HTML markup rather than a literal string. Consequently, any HTML elements, including script tags, encoded within the dynamic data are treated as structural HTML instead of plain text, bypassing Vue's default escaping boundaries.

The behavior of the browser parser upon encountering this injection is dictated by the HTML5 parsing specification, specifically the "in head noscript" insertion mode. When scripting is active in the user's browser, the parser expects only specific, non-executable elements (such as <link>, <meta>, and <style>) inside a <noscript> block located within the <head>. If the parser encounters a <script> tag within this context, it recognizes an invalid sequence. Under the HTML5 rules, the parser triggers a parse error, immediately closes the parent <noscript> element, and then processes the <script> tag as a first-class element of the <head>, leading to the immediate execution of the injected script.

Code-Level Analysis and Patch Verification

The file responsible for this vulnerability is packages/nuxt/src/head/runtime/components.ts. Within this file, the runtime component <NoScript> extracts the content of the children nodes, joins them, and updates the reactive head state. Prior to the security patch, the codebase mapped the compiled slots and committed them using an unsafe assignment to noscript.innerHTML. This bypasses standard sanitizer routines and commits raw markup directly into the SSR and client-side tree.

Below is the comparison of the vulnerable codebase against the patched codebase in the runtime components file. The critical change involves switching the target property from innerHTML to textContent, which forces the runtime to handle the data as a string literal.

// Vulnerable Implementation (Pre-Patch)
if (textContent.length > 0) {
  // Unsafely assigning slot content to innerHTML
  noscript.innerHTML = textContent.join('')
}
 
// Patched Implementation (Post-Patch)
if (textContent.length > 0) {
  // Safely assigning slot content to textContent
  noscript.textContent = textContent.join('')
}

This modification resolves the vulnerability on both the client-side and server-side rendering pipelines. On the client side, assigning to textContent ensures that the browser DOM APIs treat the input strictly as text nodes, neutralizing any embedded tag structures. On the server side, when the Unhead library serializes the virtual components into static HTML strings, it processes the textContent property by escaping characters such as <, >, and & into their safe HTML entity representations. Consequently, an attacker's payload is rendered harmlessly as text rather than being parsed as executable tags.

Exploitation Methodology

Exploiting this vulnerability requires a specific but common application pattern where dynamic variables are rendered within the <NoScript> component slot. An attacker must first identify a target endpoint that interpolates user-controlled request parameters (such as query strings or route parameters) directly inside the fallback component. Once such an endpoint is found, the attacker can deliver a reflected payload by crafting a malicious URL containing JavaScript tags.

Consider an application that renders a banner value inside the <NoScript> tag for SEO fallback purposes. The template structure of the vulnerable page is as follows:

<template>
  <div>
    <NoScript>
      You are viewing the page with the banner: {{ route.query.banner }}
    </NoScript>
  </div>
</template>

An attacker can construct a payload such as </noscript><script>alert(document.cookie)</script> and append it to the banner query parameter. When a victim loads the crafted URL, the server serializes the template, generating raw unescaped HTML within the <head> of the page.

When the client's browser receives the HTTP response containing the raw HTML, the HTML parser processes the document from top to bottom. As the parser enters the <noscript> tag within the <head>, it operates under the "in head noscript" insertion mode. Upon meeting the injected </noscript> or the raw <script> tag, the parser implicitly terminates the <noscript> element and instantiates the script block. The browser then executes the embedded JavaScript code in the security context of the vulnerable origin, allowing the attacker's script to read session tokens or modify the DOM.

Impact Assessment and Historical Significance

The impact of a successful Cross-Site Scripting attack via the <NoScript> component is significant, despite the low CVSS score of 2.3. By executing arbitrary JavaScript in the victim's browser, an attacker can access sensitive resources, such as session cookies, local storage, and CSRF tokens. This access can facilitate session hijacking, allowing the attacker to masquerade as the authenticated user and execute unauthorized actions on their behalf.

Beyond standard session compromise, XSS inside a framework like Nuxt can lead to sophisticated virtual defacement and phishing attacks. An attacker can dynamically rewrite the DOM, inject fraudulent login forms, or redirect users to malicious third-party sites. Furthermore, since Nuxt runs on both the server and the client, the injection occurs early in the document lifecycle, giving the malicious script full control over subsequent application initialization and state management.

In addition to its technical implications, GHSA-M3Q2-P4FW-W38M holds immense historical significance within the cybersecurity industry. It was discovered and reported to Anthropic's coordinated vulnerability disclosure pipeline by Claude, Anthropic's AI assistant. Triaged under reference ANT-2026-4NJYDFFM, this disclosure represents one of the earliest documented instances of a zero-day vulnerability in a major open-source web framework being autonomously identified and reported by a large language model. This milestone highlights the evolving capabilities of artificial intelligence in software security and automated code auditing.

Remediation and Long-Term Defensive Strategies

The primary remediation strategy for this vulnerability is to upgrade the Nuxt framework to a patched version. For applications running Nuxt 3, the vulnerability is resolved in version 3.21.7. For applications utilizing Nuxt 4, the issue is addressed in version 4.4.7. Upgrading ensures that the underlying @unhead/vue components use the safe textContent sink, eliminating the vulnerability at the framework level.

In environments where an immediate upgrade is not possible, developers should implement temporary mitigations. The most effective workaround is to avoid dynamic interpolation within the <NoScript> slot. Instead of placing variable data directly inside the tag, developers should restrict <NoScript> usage to static text messages. Any necessary dynamic content should be sanitized using a library like DOMPurify or converted to entities using Vue's internal utility functions prior to rendering.

Alternatively, developers can utilize Nuxt's programmatic configuration via useHead to inject fallback elements. Because the programmatic API handles data configuration separately from template slots, it enforces the use of text-safe paths. The following code pattern demonstrates how to safely configure noscript fallbacks programmatically:

useHead({
  noscript: [
    { textContent: route.query.banner }
  ]
})

By transitioning to programmatic declarations, applications ensure that the rendering engine maps properties to text nodes instead of compiling them as HTML markup.

Fix Analysis (2)

Technical Appendix

CVSS Score
2.3/ 10
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N
EPSS Probability
0.02%
Top 100% most exploited

Affected Systems

Nuxt applications using server-side rendering (SSR)Applications using Nuxt <NoScript> runtime head component with dynamic slot content

Affected Versions Detail

Product
Affected Versions
Fixed Version
nuxt
Nuxt
< 3.21.73.21.7
nuxt
Nuxt
>= 4.0.0, < 4.4.74.4.7
AttributeDetail
CWE IDCWE-79
Attack VectorNetwork (AV:N)
CVSS Score2.3 (Low)
Exploit StatusProof-of-Concept
Affected Component<NoScript> Runtime Component
Discovery MechanismAutonomous AI Discovery (Claude)

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
CWE-79
Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

The application does not neutralize or incorrectly neutralizes user-controlled input before it is placed in output that is used as a web page that is served to other users.

Vulnerability Timeline

Vulnerability patched in Nuxt main and release branches.
2026-05-28
Advisory GHSA-M3Q2-P4FW-W38M officially published and credited to Claude.
2026-06-16

References & Sources

  • [1]GitHub Advisory for GHSA-M3Q2-P4FW-W38M
  • [2]Nuxt Security Advisory Page
  • [3]Duplicate Advisory Reference (GHSA-8grp-wcq9-925q)

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

•about 5 hours ago•GHSA-JWM3-QCFW-C5PP
5.1

GHSA-jwm3-qcfw-c5pp: Security Bypass in n8n Python Code Node AST Validator

An authenticated security-bypass vulnerability in n8n allows users with workflow creation or modification privileges to bypass the Python AST security validator. By circumventing AST validation logic, attackers can execute arbitrary statements, access the task executor's root module namespace, and disclose sensitive host environment variables on self-hosted instances.

Amit Schendel
Amit Schendel
7 views•6 min read
•about 5 hours ago•GHSA-H3JJ-5F3V-3685
6.4

GHSA-H3JJ-5F3V-3685: Public API Execution Retry Authorization Bypass in n8n

An incorrect authorization vulnerability in the Public API of n8n allows authenticated users with read-only permissions to bypass access control boundaries. By invoking the execution retry endpoint, an unauthorized user can trigger workflow executions, effectively escalating their privileges from workflow:read to workflow:execute.

Amit Schendel
Amit Schendel
5 views•5 min read
•about 12 hours ago•CVE-2026-49993
5.7

CVE-2026-49993: Proprietary Source Code Exfiltration via Incomplete Same-Origin Verification in Nuxt Dev Servers

CVE-2026-49993 identifies an incomplete same-origin check validation mechanism in @nuxt/webpack-builder and @nuxt/rspack-builder dev server middleware. When the local development server is bound to a non-loopback address, cross-origin attackers can bypass verification checks by suppressing browser headers, leading to unauthorized retrieval and exfiltration of compiled source code chunks.

Amit Schendel
Amit Schendel
8 views•4 min read
•about 13 hours ago•GHSA-69QJ-PVH9-C5WG
7.5

GHSA-69QJ-PVH9-C5WG: Command Injection in yt-dlp `--exec` Option

An OS command injection vulnerability in yt-dlp before 2026.06.09 allows unauthenticated remote attackers to execute arbitrary shell commands via crafted media metadata when a user processes media using the --exec post-processing parameter with unsafe string interpolation conversions.

Alon Barad
Alon Barad
10 views•7 min read
•about 14 hours ago•GHSA-7CX2-G3H9-382P
8.1

GHSA-7CX2-G3H9-382P: Multiple Vulnerabilities in Crawl4AI Docker API (Arbitrary File Write, SSRF, CRLF Log Injection)

An in-depth technical analysis of multiple security vulnerabilities in the self-hosted Docker API server of Crawl4AI up to version 0.8.7. These flaws include a critical arbitrary file write via symlink traversal and TOCTOU weakness, CRLF log injection, webhook header injection, and SSRF filter gaps. These have been remediated in version 0.8.8.

Alon Barad
Alon Barad
5 views•6 min read
•about 15 hours ago•GHSA-F989-C77F-R2CQ
8.2

GHSA-f989-c77f-r2cq: LLM Credential Exfiltration and SSRF in Crawl4AI Docker Server

A technical evaluation of the Crawl4AI open-source web crawling and scraping library revealed a high-severity credential exfiltration vulnerability in its self-hosted Dockerized API server. The flaw arises from an unvalidated base_url parameter in request payloads and a dynamic prefix resolution mechanism that retrieves system environment variables. Unauthenticated remote attackers can leverage these features in tandem to extract host-level secrets or redirect configured LLM API keys to an external listener under their control.

Amit Schendel
Amit Schendel
6 views•6 min read