May 15, 2026·6 min read·30 visits
Svelte versions prior to 5.55.7 contain an XSS vulnerability in the `hydratable` SSR feature. Attackers can leverage the '$' replacement token in promise values to execute arbitrary JavaScript in the victim's browser.
A critical Cross-Site Scripting (XSS) vulnerability exists in the Server-Side Rendering (SSR) engine of the Svelte framework. The vulnerability occurs due to insecure promise serialization within the experimental `hydratable` feature. Attackers controlling the output of a resolved promise can inject JavaScript string replacement tokens, causing the SSR engine to duplicate template strings into executable script blocks.
The Svelte framework provides server-side rendering (SSR) capabilities to pre-render applications into HTML strings. A recent experimental feature, hydratable, allows developers to serialize promises during SSR and resolve them on the client side. This vulnerability (GHSA-f3cj-j4f6-wq85) resides specifically within the serialization logic of this feature.
The flaw requires developers to pass attacker-controlled input into a promise evaluated by the hydratable function. If the attacker supplies input containing specific JavaScript string replacement tokens, the Svelte rendering engine misinterprets the data. This behavior allows the attacker to break out of the intended string literal context and inject arbitrary JavaScript payloads into the generated HTML document.
According to CVSS v4.0 metrics, the vulnerability carries a base score of 9.1. The attack vector is network-based, requires low privileges, and mandates specific usage conditions within the target application. Once exploited, the vulnerability results in high impact to the confidentiality and integrity of the subsequent system, defined in this context as the end user's web browser.
Applications not utilizing the experimental hydratable feature remain unaffected. Organizations employing Svelte must assess their codebases for calls to this specific function that process untrusted data.
The core vulnerability stems from the insecure usage of the String.prototype.replace() method within Svelte's hydratable serialization pipeline. The vulnerable module, located at packages/svelte/src/internal/server/hydratable.js, manages the insertion of resolved promise values into a pre-computed HTML template string. The engine utilizes the uneval function from the devalue library to serialize the output safely.
When String.prototype.replace() receives a string as its second argument, the JavaScript runtime evaluates specific character sequences starting with a dollar sign ($) as special replacement patterns. For example, the token $' instructs the runtime to insert the portion of the source string that follows the matched substring. Other tokens, such as $& (matched substring) and $n (captured groups), exhibit similar dynamic behavior.
The Svelte SSR engine constructs the final template by calling .replace(placeholder, string) where the replacement string contains the attacker-controlled, serialized promise value. The devalue library correctly escapes standard HTML injection characters such as < and /. However, it does not escape the $ character, as it is a valid literal character within standard JavaScript string literals.
By supplying the $' token, an attacker forces the replace function to copy the trailing portion of the pre-computed template string and insert it directly into the serialized output. This mechanism breaks the syntax of the generated JavaScript execution block. The injected trailing string closes the intended variable assignment and allows subsequent payload bytes to execute as arbitrary code in the browser context.
The original implementation of packages/svelte/src/internal/server/hydratable.js evaluated the serialization using a string literal as the replacement parameter. The code dynamically constructed a function call r() containing the output of uneval().
// Vulnerable implementation
entry.serialized = entry.serialized.replace(placeholder, `r(${uneval(v)})`);If the attacker controls v and sets it to $', uneval(v) returns the literal string "$'". The replacement string becomes r("'"). When evaluated by String.prototype.replace(), the $' sequence is processed as a replacement token rather than a literal string, duplicating the template suffix.
The patch addresses this structural flaw by utilizing the functional form of String.prototype.replace(). When the second argument is a callback function, the JavaScript engine treats the function's return value as a strictly literal replacement string. The engine bypasses the evaluation of $ replacement tokens entirely.
// Patched implementation (commit a16ebc67bbcf8f708360195687e1b2719463e1a4)
entry.serialized = entry.serialized.replace(
placeholder,
() => `r(${uneval(v)})`
);This simple architectural change neutralizes the vulnerability class. The return string is injected exactly as constructed, ensuring that the JavaScript literal context remains bounded. The patch was uniformly applied across the core SSR module and corresponding playground components (ssr-dev.js and ssr-prod.js).
Exploitation of this vulnerability requires the target application to accept user input and pass it directly into the resolution of a hydratable promise. The attacker does not require direct access to the server infrastructure; the injection vector operates entirely through the standard application input channels.
The attacker crafts a specific string payload containing the $' token. In a standard attack, the payload combines the replacement token with standard JavaScript syntax designed to escape the current scope and execute arbitrary commands. A theoretical payload might look like $'};alert(document.domain);//.
The provided test case from the Svelte codebase demonstrates the exact mechanical failure. When the SSR engine evaluates hydratable('key', () => Promise.resolve($')), the generated HTML output is corrupted. The script tag containing the serialized state receives a duplicated section of the page template.
// Exploitation Proof of Concept
test('treats replacement tokens in hydratable promise values as literals', async () => {
const component = (renderer: Renderer) => {
hydratable('key', () => Promise.resolve(`$'`));
// ... render logic ...
};
const { head } = await Renderer.render(component as unknown as Component);
// The resulting head string contains the XSS payload
});When a victim visits the pre-rendered page, the browser parses the HTML document. The malformed <script> block, containing the attacker's payload, is executed synchronously during document parsing. This allows the attacker to execute code within the origin of the vulnerable application.
The primary impact of this vulnerability is arbitrary JavaScript execution within the context of the user's browser session. Cross-Site Scripting allows attackers to bypass the Same-Origin Policy (SOP). The severity is reflected in the CVSS v4.0 vector CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:N.
Attackers successfully exploiting this flaw gain full read and write access to the DOM of the affected application. They can exfiltrate sensitive data, including session tokens, CSRF tokens, and local storage contents. The attacker can also perform unauthorized actions on behalf of the victim by issuing authenticated API requests.
While the consequences of the XSS are severe, the attack surface is constrained by the application's architecture. The vulnerable code path strictly requires the usage of the experimental hydratable feature. Applications relying solely on standard Svelte state management or non-hydrated SSR pipelines are fundamentally immune to this vector.
The definitive remediation for this vulnerability is upgrading the svelte package to version 5.55.7 or later. The patch modifies the internal serialization logic to properly handle replacement tokens, ensuring that user input cannot alter the structural integrity of the generated HTML template.
Developers must audit their application codebases for instances of the hydratable function. If immediate patching is not feasible, implement strict input validation on all data passed into hydrated promises. Specifically, block or sanitize the dollar sign character ($) in data intended for SSR serialization.
Organizations should also enforce a strict Content Security Policy (CSP). Implementing CSP directives such as script-src with nonces or strict hash requirements significantly mitigates the impact of XSS vulnerabilities. While a CSP does not patch the underlying engine flaw, it prevents the execution of unauthorized inline scripts and external payloads.
CVSS:4.0/AV:N/AC:L/AT:P/PR:L/UI:N/VC:N/VI:N/VA:N/SC:H/SI:H/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
svelte Svelte | >= 5.46.0, < 5.55.7 | 5.55.7 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-79 |
| Attack Vector | Network |
| CVSS v4.0 | 9.1 (Critical) |
| Impact | High Confidentiality, High Integrity (Subsequent System) |
| Exploit Status | PoC Available |
| KEV Status | Not Listed |
The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
containerd is an open-source container runtime. Prior to versions 1.7.36, 2.0.13, 2.2.9, 2.3.6, and 2.4.1, a crafted OCI index graph can force very high CPU/memory usage during PullImage (before container start), causing long ContainerCreating stalls and, at larger sizes, node/runtime instability. The vulnerability occurs because containerd's image-pull descriptor graph resolution handlers processed OCI image indices and manifests recursively without enforcing boundaries on traversal depth or breadth, and without maintaining a global visited registry to count duplicate references.
An unauthenticated path traversal vulnerability exists in the Khoj AI assistant platform via the static file serving endpoint `/home/{file_path:path}`. Due to improper path sanitization when handling user input with Python's pathlib module, a remote attacker can read arbitrary files from the server's filesystem.
An argument injection vulnerability (CWE-88) in CliInvoke and AlastairLundy.CliInvoke allows local attackers to execute arbitrary system commands. By injecting double-quote characters into target file paths or arguments, attackers can terminate operating-system-level quoted boundaries and introduce new commands when shell runners are utilized.
An OS command injection vulnerability exists in the PowerShell and Cmd shell wrappers of the CliInvoke .NET library (specifically the CliInvoke.Specializations package). Under vulnerable configurations, arguments and targets are passed as a single flat string to ProcessStartInfo.Arguments, permitting double-quote breakout and execution of arbitrary secondary commands with host process privileges.
A critical-severity input validation vulnerability in the Elixir multi-party payment library `mpp` allows unauthenticated remote attackers to exhaust the transaction fee payer's wallet balance. By submitting a crafted Ethereum transaction envelope with artificially inflated gas parameters, an attacker can force the server to co-sign and commit to pay exorbitant fees, leading to severe financial loss and Denial of Service.
A critical gas draining vulnerability exists in the ZenHive mpp (Multi-Payment Protocol) library prior to version v0.6.0. By omitting validation of EIP-2930 access lists in custom 0x76 transaction envelopes, the library allows malicious clients to pad transaction payloads with dummy addresses, draining the gas sponsor's hot wallet.