CVE-2026-28815
Swift Crypto: X-Wing HPKE Decapsulation Accepts Malformed Ciphertext Length
A remote attacker can supply a short X-Wing HPKE encapsulated key and trigger an out-of-bounds read in the C decapsulation path, potentially causing a crash or memory disclosure depending on runtime protections. This issue is fixed in swift-crypto version 4.3.1.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- None
- Availability
- High
Exploit likelihood
What each source reports
NVD Score used
7.5
A remote attacker can supply a short X-Wing HPKE encapsulated key and trigger an out-of-bounds read in the C decapsulation path, potentially causing a crash or memory disclosure depending on runtime protections. This issue is fixed in swift-crypto version 4.3.1.
- Record
CVE-2026-28815- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-125
- Updated
- 2026-11-02
CVE List
7.5
A remote attacker can supply a short X-Wing HPKE encapsulated key and trigger an out-of-bounds read in the C decapsulation path, potentially causing a crash or memory disclosure depending on runtime protections. This issue is fixed in swift-crypto version 4.3.1.
- Record
CVE-2026-28815- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Weakness
- CWE-125
- Updated
- 2026-11-02
EUVDEUVD-2026-18570
7.5
A remote attacker can supply a short X-Wing HPKE encapsulated key and trigger an out-of-bounds read in the C decapsulation path, potentially causing a crash or memory disclosure depending on runtime protections. This issue is fixed in swift-crypto version 4.3.1.
- Record
EUVD-2026-18570- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-9m44-rr2w-ppp7
8.8
Swift Crypto: X-Wing HPKE Decapsulation Accepts Malformed Ciphertext Length
Summary
The X-Wing decapsulation path accepts attacker-controlled encapsulated ciphertext bytes without enforcing the required fixed ciphertext length. The decapsulation call is forwarded into a C API, which expects a compile-time fixed-size ciphertext buffer of 1120 bytes. This creates an FFI memory-safety boundary issue when a shorter Data value is passed in, because the C code may read beyond the Swift buffer.
The issue is reachable through initialization of an HPKE.Recipient, which decapsulates the provided encapsulatedKey during construction. A malformed encapsulatedKey can therefore trigger undefined behavior instead of a safe length-validation error.
Details
The decapsulate function of OpenSSLXWingPrivateKeyImpl does not perform a length check before passing the encapsulated data to the C API.
func decapsulate(_ encapsulated: Data) throws -> SymmetricKey {
try SymmetricKey(unsafeUninitializedCapacity: Int(XWING_SHARED_SECRET_BYTES)) { sharedSecretBytes, count in
try encapsulated.withUnsafeBytes { encapsulatedSecretBytes in
let rc = CCryptoBoringSSL_XWING_decap(
sharedSecretBytes.baseAddress,
encapsulatedSecretBytes.baseAddress,
&self.privateKey
)
guard rc == 1 else {
throw CryptoKitError.internalBoringSSLError()
}
count = Int(XWING_SHARED_SECRET_BYTES)
}
}
}
The C API does not have a runtime length parameter and instead expects a fixed-size buffer of 1120 bytes.
#define XWING_CIPHERTEXT_BYTES 1120
OPENSSL_EXPORT int XWING_decap(
uint8_t out_shared_secret[XWING_SHARED_SECRET_BYTES],
const uint8_t ciphertext[XWING_CIPHERTEXT_BYTES],
const struct XWING_private_key *private_key);
Since decapsulate accepts arguments of any length, an attacker controlled input can trigger an out-of-bounds read. The vulnerable code path can be reached through by initializing a HPKE.Recipient. This creates a new HPKE.Context, which decapsulates the attacker-controlled enc argument:
init<PrivateKey: HPKEKEMPrivateKey>(recipientRoleWithCiphersuite ciphersuite: Ciphersuite, mode: Mode, enc: Data, psk: SymmetricKey?, pskID: Data?, skR: PrivateKey, info: Data, pkS: PrivateKey.PublicKey?) throws {
let sharedSecret = try skR.decapsulate(enc)
self.encapsulated = enc
self.keySchedule = try KeySchedule(mode: mode, sharedSecret: sharedSecret, info: info, psk: psk, pskID: pskID, ciphersuite: ciphersuite)
}
PoC
This PoC constructs an HPKE.Recipient using the X-Wing ciphersuite and deliberately passes a 1-byte encapsulatedKey instead of the required 1120 bytes. In a normal run, the malformed input is accepted and it reaches the vulnerable decapsulation path, i.e., no size rejection occurs. In an AddressSanitizer run, the same PoC produces a dynamic-stack-buffer-overflow read, confirming memory-unsafe behavior.
//===----------------------------------------------------------------------===//
//
// PoC for X-Wing malformed ciphertext-length decapsulation:
// X-Wing decapsulation accepts malformed ciphertext length and forwards it to C.
//
// This test is intentionally unsafe and is expected to crash (or trip ASan)
// on vulnerable builds when run.
//
//===----------------------------------------------------------------------===//
#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
import XCTest
#if CRYPTO_IN_SWIFTPM && !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
// Skip tests that require @testable imports of CryptoKit.
#else
#if !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
@testable import CryptoKit
#else
@testable import Crypto
#endif
final class XWingMalformedEncapsulationPoCTests: XCTestCase {
func testShortEncapsulatedKeyHPKERecipientInit() throws {
if #available(iOS 19.0, macOS 16.0, watchOS 12.0, tvOS 19.0, macCatalyst 19.0, *) {
let…
- Record
GHSA-9m44-rr2w-ppp7- CVSS 4.0
- 8.8 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-787
- Updated
- 2026-11-02
OSV
7.5
A remote attacker can supply a short X-Wing HPKE encapsulated key and trigger an out-of-bounds read in the C decapsulation path, potentially causing a crash or memory disclosure depending on runtime protections. This issue is fixed in swift-crypto version 4.3.1.
- Record
CVE-2026-28815- CVSS 3.1
- 7.5 High
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H - Updated
- 2026-11-02
OSVGHSA-9m44-rr2w-ppp7
8.8
Swift Crypto: X-Wing HPKE Decapsulation Accepts Malformed Ciphertext Length
Summary
The X-Wing decapsulation path accepts attacker-controlled encapsulated ciphertext bytes without enforcing the required fixed ciphertext length. The decapsulation call is forwarded into a C API, which expects a compile-time fixed-size ciphertext buffer of 1120 bytes. This creates an FFI memory-safety boundary issue when a shorter Data value is passed in, because the C code may read beyond the Swift buffer.
The issue is reachable through initialization of an HPKE.Recipient, which decapsulates the provided encapsulatedKey during construction. A malformed encapsulatedKey can therefore trigger undefined behavior instead of a safe length-validation error.
Details
The decapsulate function of OpenSSLXWingPrivateKeyImpl does not perform a length check before passing the encapsulated data to the C API.
func decapsulate(_ encapsulated: Data) throws -> SymmetricKey {
try SymmetricKey(unsafeUninitializedCapacity: Int(XWING_SHARED_SECRET_BYTES)) { sharedSecretBytes, count in
try encapsulated.withUnsafeBytes { encapsulatedSecretBytes in
let rc = CCryptoBoringSSL_XWING_decap(
sharedSecretBytes.baseAddress,
encapsulatedSecretBytes.baseAddress,
&self.privateKey
)
guard rc == 1 else {
throw CryptoKitError.internalBoringSSLError()
}
count = Int(XWING_SHARED_SECRET_BYTES)
}
}
}
The C API does not have a runtime length parameter and instead expects a fixed-size buffer of 1120 bytes.
#define XWING_CIPHERTEXT_BYTES 1120
OPENSSL_EXPORT int XWING_decap(
uint8_t out_shared_secret[XWING_SHARED_SECRET_BYTES],
const uint8_t ciphertext[XWING_CIPHERTEXT_BYTES],
const struct XWING_private_key *private_key);
Since decapsulate accepts arguments of any length, an attacker controlled input can trigger an out-of-bounds read. The vulnerable code path can be reached through by initializing a HPKE.Recipient. This creates a new HPKE.Context, which decapsulates the attacker-controlled enc argument:
init<PrivateKey: HPKEKEMPrivateKey>(recipientRoleWithCiphersuite ciphersuite: Ciphersuite, mode: Mode, enc: Data, psk: SymmetricKey?, pskID: Data?, skR: PrivateKey, info: Data, pkS: PrivateKey.PublicKey?) throws {
let sharedSecret = try skR.decapsulate(enc)
self.encapsulated = enc
self.keySchedule = try KeySchedule(mode: mode, sharedSecret: sharedSecret, info: info, psk: psk, pskID: pskID, ciphersuite: ciphersuite)
}
PoC
This PoC constructs an HPKE.Recipient using the X-Wing ciphersuite and deliberately passes a 1-byte encapsulatedKey instead of the required 1120 bytes. In a normal run, the malformed input is accepted and it reaches the vulnerable decapsulation path, i.e., no size rejection occurs. In an AddressSanitizer run, the same PoC produces a dynamic-stack-buffer-overflow read, confirming memory-unsafe behavior.
//===----------------------------------------------------------------------===//
//
// PoC for X-Wing malformed ciphertext-length decapsulation:
// X-Wing decapsulation accepts malformed ciphertext length and forwards it to C.
//
// This test is intentionally unsafe and is expected to crash (or trip ASan)
// on vulnerable builds when run.
//
//===----------------------------------------------------------------------===//
#if canImport(FoundationEssentials)
import FoundationEssentials
#else
import Foundation
#endif
import XCTest
#if CRYPTO_IN_SWIFTPM && !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
// Skip tests that require @testable imports of CryptoKit.
#else
#if !CRYPTO_IN_SWIFTPM_FORCE_BUILD_API
@testable import CryptoKit
#else
@testable import Crypto
#endif
final class XWingMalformedEncapsulationPoCTests: XCTestCase {
func testShortEncapsulatedKeyHPKERecipientInit() throws {
if #available(iOS 19.0, macOS 16.0, watchOS 12.0, tvOS 19.0, macCatalyst 19.0, *) {
let…
- Record
GHSA-9m44-rr2w-ppp7- CVSS 4.0
- 8.8 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:H/SC:N/SI:N/SA:N - Weakness
- CWE-787
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
swift-cryptoSwiftURL |
4.0.0 to 4.3.0 | 4.3.1 |
swift-cryptoSwiftURL |
4.0.0 up to 4.3.1 | 4.3.1 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-28815 is a high vulnerability (CVSS 7.5) in Apple Swift-crypto, published April 3, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.49%, the 42nd percentile. Fixed in swift-crypto 4.3.1.
References
Left out here: the rest of 2 source descriptions. The JSON record has them.