Aug 6, 2026·9 min read·2 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.
A local encoding path traversal vulnerability exists in rclone versions from v1.51.0 up to v1.75.0. When non-default local encoding parameters (such as Slash, None, or Raw) are specified, rclone's standard decoder maps safely encoded fullwidth dot-dot characters back into native directory traversal components. Since the local backend historically lacked a post-resolution path containment check, these relative segments resolved outside the designated synchronization root, allowing arbitrary file creation and modification on the host system.
An security bypass vulnerability exists in Nuxt frameworks where route rules containing mixed-case characters are silently dropped during case-insensitive routing. This occurs because lookups are folded to lowercase, but keys are stored in their original casing in the route-matching trie. As a result, critical authorization middleware, such as appMiddleware, is bypassed, allowing unauthorized access to restricted pages.
CVE-2026-71316 is a high-severity vulnerability affecting the Nuxt web development framework in versions 4.4.0 up to (but excluding) 4.5.1. Due to the lack of runtime isolation in the shared server runtime storage driver, unauthenticated remote attackers can query the static-like JSON representation of a route's server-side rendered (SSR) state (_payload.json) and bypass configured page guards and application middleware to obtain highly sensitive user session records.
An unauthenticated remote code execution (RCE) vulnerability exists in Nuxt DevTools prior to version 3.3.1. The vulnerability arises from an unauthenticated RPC channel exposed over the Vite Hot Module Replacement (HMR) WebSocket server, allowing an attacker to modify file editor configurations and execute arbitrary commands under the server context.
A highly critical Server-Side Remote Code Execution (RCE) vulnerability exists in the Nuxt framework when Server Islands and the Vue runtime compiler are simultaneously enabled. This allows unauthenticated remote attackers to execute arbitrary system commands on the host process by passing a crafted component definition object to the dynamic component resolution engine via public island endpoints.
An unauthenticated remote denial of service vulnerability exists in the Nuxt framework island renderer endpoint. By transmitting large or deeply nested JSON payloads, an attacker can block the single-threaded Node.js event loop, resulting in application-wide CPU exhaustion before signature verification occurs.