CVE-2026-27120
Swift vulnerability analysis and mitigation

Overview

CVE-2026-27120 is a Cross-Site Scripting (XSS) vulnerability in Leafkit, a Swift-inspired templating language used with the Vapor web framework. The htmlEscaped function fails to properly escape HTML special characters when they appear as part of extended grapheme clusters, allowing attackers to bypass HTML escaping protections. All versions of github.com/vapor/leaf-kit prior to 1.4.1 are affected. The vulnerability was published on February 18, 2026, and carries a CVSS v3.1 base score of 6.1 (Medium) (GitHub Advisory).

Technical details

The root cause lies in a fundamental mismatch between how Swift and HTML handle Unicode: Swift strings operate on extended grapheme clusters, while HTML parsers operate on individual Unicode code points (CWE-75, CWE-79, CWE-87). The vulnerable htmlEscaped() function used replacingOccurrences(of:) or replacing() — both of which compare at the grapheme cluster level — meaning a sequence like " (U+0022 Quotation Mark) followed by ́ (U+0301 Combining Acute Accent) forms a single grapheme cluster that does not match a standalone ", so the quote is never escaped. An attacker can craft input using such combined sequences to break out of HTML attribute contexts. The fix in commit 8919e39 rewrites the function to iterate over unicodeScalars instead, ensuring each individual Unicode scalar is evaluated and escaped independently (GitHub Advisory, Patch Commit).

Impact

Successful exploitation allows an attacker to inject arbitrary HTML attributes into pages rendered by Leafkit, enabling XSS attacks in applications where user-controlled data is rendered inside HTML attribute values. This can lead to session hijacking, credential theft, malware distribution, or other client-side attacks executed in the victim's browser context. The impact is scoped to the browser (confidentiality and integrity are both rated Low), and availability is not affected; however, the scope is marked as Changed since the vulnerable component (the server) impacts resources in the browser's security context. The severity is reduced if a strict Content Security Policy (CSP) is in place (GitHub Advisory).

Exploitability

A proof-of-concept exploit is publicly documented in the GitHub Security Advisory, demonstrating a working payload using URL-encoded extended grapheme clusters (e.g., msg=%22%cc%81=1%20autofocus%20tabindex=0%20onfocus=alert(1)) to trigger JavaScript execution via an onfocus event handler injected into an HTML attribute. No privileges are required, but user interaction (a victim visiting the crafted page) is necessary. There is no evidence of active in-the-wild exploitation at this time, and the vulnerability is not listed in the CISA KEV catalog. The EPSS score is approximately 0.029% (4th percentile), indicating a low near-term exploitation probability (GitHub Advisory).

Exploitation steps

  1. Identify a vulnerable target: Find a Vapor web application using Leafkit versions prior to 1.4.1 that renders user-controlled input inside an HTML attribute in a .leaf template (e.g., <div title="#(msg)">).
  2. Craft the bypass payload: Construct input that combines an HTML special character (e.g., " U+0022) with a Unicode combining character (e.g., U+0301 Combining Acute Accent) to form an extended grapheme cluster that Swift's string comparison will not match against the plain special character.
  3. Inject the malicious attribute: Submit the crafted payload via the application's input mechanism (e.g., HTTP POST body): msg=%22%cc%81=1%20autofocus%20tabindex=0%20onfocus=alert(1). The %22%cc%81 sequence is the URL-encoded form of (quote + combining accent).
  4. Bypass escaping: Leafkit's htmlEscaped() function fails to escape the " because it is part of a grapheme cluster, so the raw quote character passes through into the rendered HTML, breaking out of the attribute value context.
  5. Achieve XSS: The rendered HTML now contains an injected onfocus=alert(1) attribute. When a victim visits the page and the element receives focus (aided by autofocus tabindex=0), the JavaScript executes in their browser, enabling session theft, credential harvesting, or further attacks (GitHub Advisory).

Indicators of compromise

  • Network: HTTP POST requests to Vapor application endpoints containing URL-encoded sequences combining HTML special characters with Unicode combining characters (e.g., %22%cc%81, %3c%cc%81, %26%cc%81) in user-supplied parameters.
  • Logs: Application access logs showing requests with unusual Unicode sequences in parameter values, particularly those mixing ASCII special characters (quotes, angle brackets, ampersands) with combining diacritical marks (U+0300–U+036F range).
  • Rendered Output: HTML source of served pages containing unescaped ", <, >, &, or ' characters within attribute values, or unexpected event handler attributes (e.g., onfocus=, onmouseover=, onerror=) injected into HTML elements.
  • Browser-Side: Client-side JavaScript errors or unexpected alert() dialogs triggered on page load or focus events, which may indicate active XSS probing (GitHub Advisory).

Mitigation and workarounds

Upgrade github.com/vapor/leaf-kit to version 1.4.1 or later, which rewrites the htmlEscaped() function to iterate over Unicode scalars rather than grapheme clusters, correctly escaping all HTML special characters regardless of combining character context (patch commit 8919e39) (Patch Commit). As a defense-in-depth measure while patching, implement a strict Content Security Policy (CSP) header to limit the impact of any XSS that does occur. Additionally, audit all Leaf templates for instances where user-controlled variables are rendered inside HTML attributes, and consider adding server-side input validation to reject or strip combining Unicode characters from sensitive fields (GitHub Advisory).

Additional resources


SourceThis report was generated using AI

Related Swift vulnerabilities:

CVE ID

Severity

Score

Technologies

Component name

CISA KEV exploit

Has fix

Published date

CVE-2026-28975MEDIUM6.9
  • Swift logoSwift
  • SwiftNIOExtras
NoYesJun 12, 2026
CVE-2026-47121MEDIUM6.1
  • Swift logoSwift
  • sparkle
NoYesJul 21, 2026
CVE-2026-64785MEDIUM5.3
  • Swift logoSwift
  • swift-nio-http2
NoYesJul 23, 2026
CVE-2026-28898MEDIUM5.3
  • Swift logoSwift
  • SwiftNIOHPACK
NoYesJun 25, 2026
CVE-2026-47122MEDIUM4.2
  • Swift logoSwift
  • sparkle
NoNoJul 21, 2026

Free Vulnerability Assessment

Benchmark your Cloud Security Posture

Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.

Request assessment

Get a personalized demo

Ready to see Wiz in action?

"Best User Experience I have ever seen, provides full visibility to cloud workloads."
David EstlickCISO
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
Adam FletcherChief Security Officer
"We know that if Wiz identifies something as critical, it actually is."
Greg PoniatowskiHead of Threat and Vulnerability Management