Aug 6, 2026·9 min read·25 visits
Unauthenticated remote attackers can inject arbitrary HTML elements or instantiate globally-registered Vue components via the /__nuxt_island/ endpoint by exploiting attribute fallthrough on polymorphic root elements.
CVE-2026-71318 is a vulnerability in Nuxt where unauthenticated remote attackers can trigger unauthorized component instantiation and arbitrary HTML element injection. This security flaw is caused by default attribute inheritance (fallthrough) combined with polymorphic root components inside island components accessible via the /__nuxt_island/ endpoint. Attackers can bypass standard routing checks to instantiate globally registered components or inject raw HTML tags like iframes. This vector is highly reachable since it does not require enabling the vue.runtimeCompiler option. It is patched in Nuxt versions 3.21.10 and 4.5.1.
Nuxt Server Islands represent a specialized framework feature that enables developers to isolate and render server-side components within a standard client-side Nuxt or Vue.js application. This mechanism improves performance and security boundaries by allowing complex server-bound operations—such as direct database queries or secure API integrations—to run strictly within the server environment. The rendered HTML is then securely streamed to the client and dynamically mounted into the client-side DOM. This architecture relies on a dedicated server-side routing endpoint, specifically mapped to the /__nuxt_island/ path.\n\nCommunication between the client-side runtime and the backend Island endpoint is facilitated through query parameters or POST request body payloads containing parameters designated as props. Under normal operations, when a user requests an island, the Nuxt framework resolves the target component, deserializes the client-provided props, and executes Vue's Server-Side Renderer (SSR) engine to compile the component down to static HTML. This model assumes that the parameters sent by the client are strictly mapped to the properties explicitly declared in the target component's local setup.\n\nThe vulnerability identified as CVE-2026-71318 breaks this security assumption by exploiting Vue's default attribute inheritance, commonly referred to as attribute fallthrough. When a parent element passes attributes to a child component, any attribute not explicitly registered in the child component's declared props automatically falls through to the component's single root element. When this root element is a polymorphic component (which dynamically resolves elements based on an incoming attribute), an unauthenticated remote attacker can hijack the dynamic resolution process. This facilitates the injection of arbitrary HTML tags or the unauthorized instantiation of globally-registered components without requiring the vue.runtimeCompiler configuration option to be enabled.
The technical root cause of CVE-2026-71318 resides at the intersection of Vue's default attribute fallthrough behavior and the architectural patterns of polymorphic UI design systems. In Vue, when attributes are passed to a component, the framework parses the props declaration of that component. If a property in the input payload does not match any declared prop, it is treated as an attribute fallthrough candidate. These unregistered attributes are automatically bound to the component's root DOM node or outermost component child.\n\nModern UI component libraries, such as @nuxt/ui and reka-ui, utilize polymorphic design conventions to provide highly flexible components. These polymorphic elements (for example, buttons, cards, or layout containers) accept a designated property—conventionally named as or asChild—which determines the underlying element type to be rendered. Behind the scenes, the parent wrapper forwards this dynamic tag directly to Vue's internal rendering engine using the dynamic <component :is="as"> tag or the equivalent resolveDynamicComponent API.\n\nIf an application implements a Nuxt Server Island where the single root element is a polymorphic component, and the island component itself does not explicitly declare the as property within its own local props schema, the vulnerability manifests. When an unauthenticated remote attacker issues a request to the /__nuxt_island/ endpoint with an as parameter, the Nuxt router extracts the value and forwards it to the island's rendering lifecycle. Since as is not defined locally in the island's props, Vue's compiler initiates the fallthrough process, forwarding the string value directly to the polymorphic root element.\n\nOnce the root element receives the forwarded as attribute, its internal logic evaluates the dynamic component binding <component :is="as">. This causes the Server-Side Renderer to resolve the arbitrary, attacker-supplied string. The engine attempts to match the string against standard HTML tags or globally registered Vue components, executing the instantiation phase in the server runtime. Because this dynamic resolution occurs natively inside Vue's core virtual DOM renderer, it completely bypasses standard template compilers, meaning that the vulnerability is fully exploitable even in production environments where vue.runtimeCompiler is disabled.
Analyzing the vulnerable code path vs. the patched code path clarifies the mitigation strategy deployed by the Nuxt maintenance team. In the vulnerable implementation of the Nuxt Server Island route handler, properties sent by the client were parsed and immediately forwarded to the internal rendering pipeline. There was no inspection of the keys within the client-provided props object, which allowed arbitrary parameters to enter the Vue render lifecycle unchecked.\n\nThe remediation implemented in Nuxt versions 3.21.10 and 4.5.1 introduces a validation block designed to sanitize the incoming props object at the HTTP router boundary. The patch specifically targets the as property to neutralize the implicit fallthrough attack vector. If the parser identifies a top-level key named as within the client-supplied props, it aborts the execution flow immediately and throws a structured error.\n\nThe conceptual implementation of the patched handler is structured as follows:\n\ntypescript\n// Conceptual patch applied within the Server Island request handler\nexport default defineEventHandler(async (event) => {\n const body = await readBody(event).catch(() => ({}));\n const props = body.props || getQuery(event).props || {};\n\n // Blocklist check targeting the polymorphic 'as' attribute\n if (props && typeof props === 'object' && 'as' in props) {\n throw createError({\n statusCode: 400,\n statusMessage: 'Bad Request: Top-level "as" prop is not allowed.'\n });\n }\n\n // Standard rendering pipeline continues safely if check passes\n});\n\n\nBy introducing this blocklist check at the edge, the Nuxt framework ensures that any attempt to abuse the as fallthrough vector is caught and discarded before Vue's dynamic compiler processes the payload. However, this fix represents a localized, blocklist-driven control. It relies entirely on the assumption that the as parameter is the sole mechanism used to drive polymorphic component rendering across the target application's dependency tree, which introduces structural bypass opportunities.
To exploit CVE-2026-71318, an attacker must first locate a vulnerable server island component that employs a polymorphic root element. Attackers typically map the public attack surface by analyzing client-side JavaScript bundles, identifying paths containing /__nuxt_island/, and mapping the names of registered server components. If a target component (such as MyIsland) utilizes a root element from a framework like @nuxt/ui that supports the as prop, the endpoint is vulnerable.\n\nOnce the target is identified, the attacker crafts a malicious HTTP request to trigger the rendering of the island with injected attributes. The attacker can use either a GET request with query parameters or a POST request with a JSON body payload. By passing the as parameter within the client-supplied props, the attacker overrides the tag of the root element with a target element, such as an iframe or a global layout component, along with necessary configuration parameters like src or to.\n\nhttp\nPOST /__nuxt_island/MyIsland HTTP/1.1\nHost: target-app.local\nContent-Type: application/json\n\n{\n "props": {\n "as": "iframe",\n "src": "https://malicious.example.com"\n }\n}\n\n\nWhen the server-side engine receives this payload, it compiles the template. Because the island does not filter out the as prop, the compiler treats it as a fallthrough attribute and attaches it to the polymorphic root button. The dynamic renderer resolves iframe and compiles the output to an HTML string. The server's HTTP response then returns the fully-rendered iframe containing the malicious source URL, which executes seamlessly within the victim's browser session. This enables secondary payloads such as cross-site scripting (XSS) or credential extraction.
The security impact of CVE-2026-71318 is determined by the specific elements and global components accessible within the target application's runtime. The vulnerability has been assigned a CVSS v3.1 score of 4.8, reflecting its medium-severity status. Although the vulnerability allows unauthorized element instantiation, it does not provide direct, unauthenticated remote code execution (RCE) because Vue's dynamic component resolution resolves components statically from the registry rather than compiling arbitrary string templates.\n\nThe primary risk associated with this vulnerability is arbitrary HTML element injection. An attacker can force the server to render malicious <iframe> tags or deceptive <a> redirect links. This capability can be leveraged to execute sophisticated client-side attacks, such as clickjacking, credential phishing, or cross-site scripting (XSS), where the injected frame hosts a malicious site that appears under the trusted domain's SSL context.\n\nFurthermore, the attack vector allows attackers to instantiate any globally-registered Vue component. In complex enterprise Nuxt applications, developers often register components globally to simplify routing or state management. If sensitive administrative interfaces, data grids, or form components are globally registered, an attacker can force the server to instantiate these components. This exposure can result in the leakage of internal application structures, localized metadata, or sensitive interface templates that would otherwise remain hidden from unauthenticated users.
An analysis of the official framework-level patch reveals that while it addresses the immediate proof-of-concept vector, it is fundamentally a localized blocklist check. Because it only intercepts the exact key 'as', multiple conceptual bypasses exist that leave applications vulnerable depending on how their internal components are structured and bound.\n\nThe first bypass involves alternative polymorphic property names. UI systems, custom components, and third-party libraries frequently use different attributes to achieve polymorphism, such as tag, is, component, asChild, or elementType. If an island component utilizes a root node bound to <component :is="tag">, an attacker can bypass the patch by supplying a tag parameter instead of as. The framework's validation check will overlook this parameter, allowing the fallthrough mechanism to execute unchecked.\n\nThe second bypass relies on nested property structures and object spreading. Nuxt's blocklist check only inspects the top-level keys of the props object. If an island component accepts a configuration object and spreads it onto a root element using Vue's v-bind directive (e.g., <UButton v-bind="props.config">), the validation check is bypassed. An attacker can nest the as property inside the config object, preventing the top-level filter from triggering while still achieving polymorphic injection downstream.\n\njson\n{\n "props": {\n "config": {\n "as": "iframe",\n "src": "https://malicious.example.com"\n }\n }\n}\n\n\nFinally, explicit property forwarding bypasses the validation. If a developer explicitly declares a prop on the island component (such as componentType) and manually binds it to a dynamic component, the framework-level patch does not apply. The validation filter only scans for the literal key 'as' in raw inputs, leaving custom dynamic implementations fully exposed. This demonstrates that developers must implement application-level defenses rather than relying solely on framework patches.
CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
nuxt Nuxt | >= 3.1.0, < 3.21.10 | 3.21.10 |
nuxt Nuxt | >= 4.0.0, < 4.5.1 | 4.5.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-20 |
| Attack Vector | Network |
| CVSS v3.1 | 4.8 (Medium) |
| EPSS Score | N/A |
| Impact | HTML Injection / Component Hijacking |
| Exploit Status | Proof-of-Concept |
| KEV Status | Not Listed |
The product receives input or data, but does not validate or incorrectly validates that the input has the properties that are required to process the data safely.
CVE-2026-107387 is a high-impact uncontrolled memory allocation vulnerability in music-metadata, a widely used Node.js metadata parser. The flaw occurs in the APEv2 tag parser, where the library reads an attacker-controlled 32-bit integer indicating the tag size and immediately requests a corresponding heap buffer reservation. Because this allocation occurs before validating if the input stream actually contains those bytes, an attacker can supply a minuscule audio file to trigger large, disproportionate allocations, resulting in heap exhaustion and an uncatchable process-wide Out of Memory (OOM) crash.
An input validation vulnerability exists in music-metadata versions prior to 11.16.0, where parsing a crafted MP4 file containing a sample-description (stsd) box with a zero-value size entry causes a synchronous infinite loop and memory exhaustion, resulting in complete Denial of Service.
A path traversal vulnerability in datamodel-code-generator allows remote attackers to write or overwrite arbitrary files on the local host filesystem via a manipulated Protobuf schema containing malicious weak import paths.
PraisonAI is vulnerable to an arbitrary local file read vulnerability prior to version 4.6.78. The flaw is in the ContextGatherer component, where validation checks are executed only after files are parsed and appended to the context bundle, bypassing security constraints.
An algorithmic complexity vulnerability (CWE-770) in the Excelize library allows remote attackers to cause resource exhaustion (100% CPU usage) via a crafted Microsoft Excel spreadsheet. This occurs because the look-ahead row index parsing in Rows.Columns() fails to enforce upper boundary limits, enabling an out-of-bounds row index to trigger an infinite seek loop inside the Rows iterator.
An unauthenticated Server-Side Request Forgery (SSRF) vulnerability exists in Ghost CMS from version 6.54.1 to 6.65.0. The vulnerability stems from a validation bypass in the favicon resolution logic within the bookmark-fetching subsystem, which allows remote, unauthenticated attackers to trigger arbitrary HTTP requests to the local host and internal networks. This bypass circumvents the custom DNS-level IP blocklist controls configured globally in the application.