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



CVE-2026-27901

Svelte SSR XSS: When innerText Betrays You

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 27, 2026·5 min read·68 visits

Executive Summary (TL;DR)

Svelte's SSR compiler failed to escape data bound to `innerText` and `textContent` on `contenteditable` elements. This allows attackers to inject malicious HTML/JS scripts that execute when the page is rendered on the server. Fixed in v5.53.5.

In the world of web security, `innerText` is supposed to be the good guy—the safe alternative to the chaotic evil of `innerHTML`. Developers are taught that assigning text to `innerText` automatically escapes HTML entities, neutralizing Cross-Site Scripting (XSS) attacks before they start. But CVE-2026-27901 flips the script. In Svelte versions prior to 5.53.5, the Server-Side Rendering (SSR) engine treated `bind:innerText` on `contenteditable` elements as raw HTML injection. This effectively turned a safety feature into a direct pipeline for remote code execution in the victim's browser, proving once again that in SSR, everything is just string concatenation waiting to go wrong.

The Server-Side Illusion

We often forget that Server-Side Rendering (SSR) is, at its core, a glorified string concatenation engine. When you write a component in a modern framework like Svelte, you aren't manipulating a DOM; you are instructing a compiler to build a massive string of HTML to chuck at the browser. In the browser (the client), the DOM API is your bodyguard. If you set element.innerText = "<script>", the browser dutifully converts that to &lt;script&gt;. You are safe.

But on the server? There is no DOM. There is only text. The framework has to simulate that safety by manually running escape functions on every piece of dynamic data before stitching it into the HTML string. If the framework developers miss just one spot, that safety evaporates.

This vulnerability is a classic case of that simulation breaking down. Svelte's compiler, usually rigorous about sanitization, had a blind spot for contenteditable elements. It assumed that if you were binding data to an editable area, you probably wanted the raw content, effectively treating innerText (the safe one) exactly like innerHTML (the dangerous one). It’s like labeling a bottle of nitroglycerin "Water" because they're both liquids.

The Flaw: Identity Crisis

The root cause lies deep within the Svelte compiler's transformation phase, specifically in how it handles attributes during SSR. The logic serves to take your high-level Svelte code and transpile it into efficient JavaScript that generates HTML strings.

When the compiler encountered a contenteditable element, it had to decide how to render the initial state. The logic checked if the binding was for innerText, textContent, or innerHTML. Tragically, the code grouped all three together. It assumed that because contenteditable allows rich text editing in some contexts, the developer must want the raw HTML output for all bindings.

This is a logic error, not a buffer overflow or a memory corruption. The compiler simply failed to apply the $.escape() utility to innerText and textContent bindings. It passed the raw expression directly into the final HTML output buffer. So, when the server renders <div contenteditable bind:innerText={userInput}>, it doesn't output <div>&lt;script&gt;...</div>; it outputs <div><script>...</div>.

The Smoking Gun

Let's look at the code responsible for this betrayal. The vulnerability lived in packages/svelte/src/compiler/phases/3-transform/server/visitors/shared/element.js. This file dictates how elements are constructed during the server-side build.

Before the fix, the code looked something like this:

// The "Oops" Moment
if (is_content_editable_binding(attribute.name)) {
    // Whether it's innerHTML, innerText, or textContent,
    // it just dumps the raw expression into content.
    content = expression;
}

It’s almost insultingly simple. The fix involves explicitly checking the attribute name and applying the escape function if it's not innerHTML.

After the fix (v5.53.5):

if (attribute.name === 'innerHTML') {
    // innerHTML stays raw (dangerous by design)
    content = expression;
} else if (
    is_content_editable_binding(attribute.name) ||
    (attribute.name === 'value' && node.name === 'textarea')
) {
    // EVERYTHING ELSE GETS ESCAPED
    content = b.call('$.escape', expression);
}

That b.call('$.escape', expression) is the difference between a functional website and a compromised user base.

The Exploit: Scripting the Server

Exploiting this requires a scenario where you render user-controlled input into a contenteditable div using SSR. This is common in collaborative editing apps, CMS interfaces, or rich-text comment sections that want to be SEO-friendly.

Here is the attack chain:

  1. The Injection: An attacker submits a profile bio or comment containing: <img src=x onerror=alert(document.cookie)>.
  2. The Storage: The backend saves this string to the database.
  3. The Rendering: A user visits the profile page. The server fetches the string and renders the Svelte component.

Vulnerable Component:

<script>
  let bio = $props.bio; // "<img src=x onerror=..."
</script>
 
<!-- The trap is set -->
<div contenteditable bind:innerText={bio}></div>
  1. The Execution: Svelte generates the HTML string. Because of the bug, the output is: <div contenteditable><img src=x onerror=alert(document.cookie)></div>

  2. The Payload: The victim's browser parses this HTML. It sees the img tag, tries to load x, fails, and triggers the onerror event, executing the JavaScript. The attacker now has the victim's session tokens.

Why Should We Panic?

While the CVSS score is a "Medium" 5.3, do not let that lull you into a false sense of security. The score is dampened by the complexity (AC:H) required—specifically, you need a contenteditable element bound to user input and SSR enabled. That is not every app, but it is exactly the kind of setup used by modern, rich web applications (think Notion clones, document editors, or social platforms).

If you are hit by this, the impact is full Stored XSS. This isn't just an alert box; it's session hijacking, forced actions, or phishing via DOM manipulation. Furthermore, because the payload comes from the server's initial HTML response, it executes immediately upon page load, often before client-side frameworks or hydration logic can intervene. It bypasses any client-side sanitization logic you might have running in onMount because the damage is done before the component even mounts.

The Fix: Upgrade or Die

The remediation is straightforward: Update svelte to version 5.53.5 immediately.

If you cannot update right now (perhaps you enjoy living dangerously or have strict change freezes), you must audit your codebase for bind:innerText or bind:textContent on elements that also have the contenteditable attribute.

Workaround: Stop binding directly. Instead, sanitize the data before passing it to the component context, or use a manual binding approach that doesn't rely on the vulnerable SSR path. But really, just update the package. It's a patch-level update designed specifically to fix this.

Official Patches

SvelteCommit 0df5abc: Fix SSR escaping for contenteditable bindings

Fix Analysis (1)

Technical Appendix

CVSS Score
5.3/ 10
CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:L/VI:N/VA:N/SC:H/SI:H/SA:N
EPSS Probability
0.04%
Top 86% most exploited

Affected Systems

Svelte Framework (npm package)

Affected Versions Detail

Product
Affected Versions
Fixed Version
svelte
sveltejs
< 5.53.55.53.5
AttributeDetail
CVE IDCVE-2026-27901
CWE IDCWE-79 (XSS)
CVSS Score5.3 (Medium)
Attack VectorNetwork
ImpactCross-Site Scripting (XSS)
Fixed Version5.53.5

MITRE ATT&CK Mapping

T1189Drive-by Compromise
Initial Access
T1059.007Command and Scripting Interpreter: JavaScript
Execution
CWE-79
Cross-site Scripting

Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')

Known Exploits & Detection

GitHub AdvisoryOfficial PoC demonstrating contenteditable bypass

Vulnerability Timeline

Patch Committed to Main Branch
2026-02-25
CVE Published
2026-02-26
GHSA Advisory Released
2026-02-26

References & Sources

  • [1]GHSA-phwv-c562-gvmh
  • [2]NVD - CVE-2026-27901

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

•27 minutes ago•CVE-2026-14669
8.8

CVE-2026-14669: PostgreSQL to_char() Timezone Abbreviation Heap-Based Buffer Overflow

CVE-2026-14669 is a critical heap-based buffer overflow vulnerability in PostgreSQL's date/time formatting function to_char(timestamptz). The flaw arises from unsafe copying of user-controlled timezone abbreviations into a fixed-size internal buffer. An authenticated database user can trigger this issue by setting a long POSIX timezone abbreviation containing custom formatting, allowing them to overwrite adjacent heap structures and hijack execution control to achieve remote code execution (RCE) with the privileges of the 'postgres' operating system user.

Alon Barad
Alon Barad
1 views•6 min read
•2 days ago•CVE-2026-63462
7.5

CVE-2026-63462: Unauthenticated Stack Overflow Denial of Service in Unleash Server

An unauthenticated remote denial of service vulnerability exists in the Unleash feature management platform. By submitting a crafted JSON payload containing deeply nested structures to an OpenAPI-validated endpoint, an attacker can trigger uncontrolled recursion within the error formatting module. This leads to a call-stack exhaustion (RangeError: Maximum call stack size exceeded) inside the Node.js runtime, causing the service to crash immediately without recovery.

Alon Barad
Alon Barad
11 views•6 min read
•2 days ago•CVE-2026-63004
5.5

CVE-2026-63004: Server-Side Request Forgery in Unleash Addon and Integration Subsystem

CVE-2026-63004 is a server-side request forgery (SSRF) vulnerability in the Unleash feature management platform. Authenticated administrators with CREATE_ADDON or UPDATE_ADDON privileges can exploit this vulnerability to initiate requests to loopback addresses, private networks, and cloud metadata endpoints, potentially leading to information disclosure and credential extraction.

Amit Schendel
Amit Schendel
8 views•8 min read
•2 days ago•CVE-2026-63466
4.1

CVE-2026-63466: Process-Wide Security Degradation via Global Module Mutation in Unleash

Prior to version 8.0.3, Unleash's Markdown event formatter directly mutated the global template-escaping function of the shared mustache Node.js module, resulting in a process-wide security degradation where HTML/Markdown escaping was permanently disabled for the application lifetime.

Alon Barad
Alon Barad
3 views•6 min read
•2 days ago•CVE-2026-76904
9.8

CVE-2026-76904: Unauthenticated SQL Injection in GeoTools PostGIS DataStore Component

A critical SQL injection vulnerability exists in the GeoTools open-source Java library. This vulnerability is situated within the post-processing phase of OGC Filter conversion inside the PostGIS DataStore module. Specifically, the `jsonArrayContains` function does not validate or sanitize its arguments before constructing PostgreSQL SQL/JSON path evaluation queries. An unauthenticated remote attacker can exploit this weakness by submitting crafted filters via standard OGC services like WFS or WMS to execute arbitrary SQL commands on the underlying database system.

Alon Barad
Alon Barad
13 views•5 min read
•2 days ago•CVE-2026-61824
8.2

CVE-2026-61824: High-Severity Cross-Site Scripting (XSS) via Unsanitized Site Extractors in Defuddle

CVE-2026-61824 is a high-severity Cross-Site Scripting (XSS) vulnerability in kepano/defuddle before version 0.19.1. Custom site extractors for platforms such as X/Twitter, Substack, and YouTube constructed HTML representations via template string interpolation without output escaping. This allowed malicious pages to bypass standard parser sanitization routines and execute arbitrary JavaScript.

Amit Schendel
Amit Schendel
6 views•7 min read