Released August 17, 2026

CVE-2026-43795

CVSS 4.3 severity medium CWE-119 vector CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:N/A:L

Overview

Impact:

Description: Processing maliciously crafted web content may lead to an unexpected Safari crash

Researchers: wwwlk

Key insight. The nested credProps lookup reused the outer iterator and compared the submap’s find() result against the OUTER map’s end(), so a missing ‘rk’ key dereferenced an iterator from the wrong container.

Patch Details

diff --git a/Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientOutputs.cpp b/Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientOutputs.cpp
index 39563d3ba66d..897f6a34e6a9 100644
--- a/Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientOutputs.cpp
+++ b/Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientOutputs.cpp
@@ -49,9 +49,10 @@ std::optional<AuthenticationExtensionsClientOutputs> AuthenticationExtensionsCli
     it = decodedMap.find(cbor::CBORValue("credProps"));
     if (it != decodedMap.end() && it->second.isMap()) {
         CredentialPropertiesOutput credProps;
-        it = it->second.getMap().find(cbor::CBORValue("rk"));
-        if (it != decodedMap.end() && it->second.isBool())
-            credProps.rk = it->second.getBool();
+        const auto& credPropsMap = it->second.getMap();
+        auto credPropsIt = credPropsMap.find(cbor::CBORValue("rk"));
+        if (credPropsIt != credPropsMap.end() && credPropsIt->second.isBool())
+            credProps.rk = credPropsIt->second.getBool();
         clientOutputs.credProps = credProps;
     }
 
diff --git a/Tools/TestWebKitAPI/Tests/WebCore/CBORReaderTest.cpp b/Tools/TestWebKitAPI/Tests/WebCore/CBORReaderTest.cpp
index a8af4b1fa479..3b6c2d114d04 100644
--- a/Tools/TestWebKitAPI/Tests/WebCore/CBORReaderTest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebCore/CBORReaderTest.cpp
@@ -31,6 +31,7 @@
 
 #if ENABLE(WEB_AUTHN)
 
+#include <WebCore/AuthenticationExtensionsClientOutputs.h>
 #include <WebCore/CBORReader.h>
 #include <limits>
 #include <utility>
@@ -764,6 +765,20 @@ TEST(CBORReaderTest, TestUnsupportedSimplevalue)
     }
 }
 
+TEST(CBORReaderTest, AuthExtensionsFromCBOR_CredPropsWithoutRk)
+{
+    // CBOR encoding of {"credProps": {}} — credProps map present but no "rk" key.
+    // a1                          -- map(1)
+    //    69                       -- text(9)
+    //       63726564 50726f7073   -- "credProps"
+    //    a0                       -- map(0)
+    Vector<uint8_t> cborData { 0xa1, 0x69, 0x63, 0x72, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x70, 0x73, 0xa0 };
+    auto result = WebCore::AuthenticationExtensionsClientOutputs::fromCBOR(cborData);
+    ASSERT_TRUE(result.has_value());
+    ASSERT_TRUE(result->credProps.has_value());
+    EXPECT_FALSE(result->credProps->rk);
+}
+
 } // namespace TestWebKitAPI
 
 #endif // ENABLE(WEB_AUTHN)

Background

Advisory: Apple Security Advisory

Attribute Value
CVE CVE-2026-43795
Bugzilla 313452
Component WebCore
Bug Class OOB
Severity medium
Commit ce11a67281dafaa7…
Advisory Apple Advisory

Terminology

  • CBOR — Concise Binary Object Representation, the binary map/array format WebAuthn uses for authenticator data and extension outputs.
  • credProps extension — A WebAuthn client extension whose output is a map that may contain a boolean ‘rk’ (resident key) flag.
  • Iterator container mismatch — Comparing or dereferencing an iterator against a different container’s end() is undefined behavior and can read invalid memory.

Root Cause Analysis

This fixes a logic error — comparing and dereferencing a hash-map iterator against the wrong container — in WebAuthn CBOR parsing. AuthenticationExtensionsClientOutputs::fromCBOR decodes the top-level CBOR map (decodedMap), finds the ‘credProps’ entry, and then tried to look up the nested ‘rk’ key by REUSING the same iterator variable: it = it->second.getMap().find(cbor::CBORValue(“rk”)), then tested if (it != decodedMap.end() && it->second.isBool()). The find() runs on the nested credProps submap and returns an iterator into THAT submap, but the code compared it against decodedMap.end() — the end of the OUTER map — and reassigned the outer iterator in the process. Comparing iterators from two different containers is undefined behavior, and when ‘rk’ is absent from credProps the submap’s find() returns the submap’s end iterator; testing it against the wrong end and then dereferencing it->second reads past/into an invalid iterator, causing an out-of-bounds read / crash. The fix takes a stable reference to the nested map (const auto& credPropsMap = it->second.getMap()), searches it with a separate iterator (credPropsIt), and compares against credPropsMap.end() before reading credPropsIt->second. The restored invariant is that an iterator is only compared and dereferenced against its own container. The regression test decodes {“credProps”: {}} (credProps present, no ‘rk’) and expects a valid result with credProps->rk false.

Attack Path

1. Return a crafted assertion

A malicious authenticator/site supplies a WebAuthn response whose CBOR client-extension outputs contain a credProps map with no ‘rk’ key.

2. Parse the extension outputs

WebKit calls AuthenticationExtensionsClientOutputs::fromCBOR, which searches the credProps submap for ‘rk’.

3. Compare against the wrong end

The submap’s end iterator is compared to the outer map’s end (undefined behavior) and then dereferenced.

4. Crash / OOB read

Dereferencing the invalid iterator reads out of bounds, crashing the WebContent process.

Impact Assessment

An out-of-bounds read / crash in the WebContent process when parsing attacker-supplied WebAuthn extension-output CBOR. The primitive is a mis-compared/mis-dereferenced iterator on the parsing path, which the advisory frames as a crash; it is a memory-safety bug reachable wherever WebAuthn assertion/attestation responses are processed.

Audit Directions

Same file: nested map lookups

Audit AuthenticationExtensionsClientOutputs and nearby WebAuthn CBOR parsers for find() results compared to a different map’s end() or reused iterator variables across nested maps.

CBOR getMap()/find patterns

Grep for getMap().find(…) followed by comparison to an outer .end(); ensure each comparison uses the same map the find() ran on.

Changed Functions

Function File Change Note
AuthenticationExtensionsClientOutputs::fromCBOR Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientOutputs.cpp modified Searches the nested credProps map with its own iterator (credPropsIt) compared against credPropsMap.end(), instead of reusing the outer iterator and comparing to decodedMap.end().
CBORReaderTest.AuthExtensionsFromCBOR_CredPropsWithoutRk Tools/TestWebKitAPI/Tests/WebCore/CBORReaderTest.cpp added Regression test decoding {“credProps”:{}} to ensure a missing ‘rk’ key no longer misuses the iterator.

Files Changed

Source Files

  • Source/WebCore/Modules/webauthn/AuthenticationExtensionsClientOutputs.cpp

Test Files

  • Tools/TestWebKitAPI/Tests/WebCore/CBORReaderTest.cpp

Regression Test

The fix ships this proof-of-concept / regression test:

diff --git a/Tools/TestWebKitAPI/Tests/WebCore/CBORReaderTest.cpp b/Tools/TestWebKitAPI/Tests/WebCore/CBORReaderTest.cpp
index a8af4b1fa479..3b6c2d114d04 100644
--- a/Tools/TestWebKitAPI/Tests/WebCore/CBORReaderTest.cpp
+++ b/Tools/TestWebKitAPI/Tests/WebCore/CBORReaderTest.cpp
@@ -31,6 +31,7 @@
 
 #if ENABLE(WEB_AUTHN)
 
+#include <WebCore/AuthenticationExtensionsClientOutputs.h>
 #include <WebCore/CBORReader.h>
 #include <limits>
 #include <utility>
@@ -764,6 +765,20 @@ TEST(CBORReaderTest, TestUnsupportedSimplevalue)
     }
 }
 
+TEST(CBORReaderTest, AuthExtensionsFromCBOR_CredPropsWithoutRk)
+{
+    // CBOR encoding of {"credProps": {}} — credProps map present but no "rk" key.
+    // a1                          -- map(1)
+    //    69                       -- text(9)
+    //       63726564 50726f7073   -- "credProps"
+    //    a0                       -- map(0)
+    Vector<uint8_t> cborData { 0xa1, 0x69, 0x63, 0x72, 0x65, 0x64, 0x50, 0x72, 0x6f, 0x70, 0x73, 0xa0 };
+    auto result = WebCore::AuthenticationExtensionsClientOutputs::fromCBOR(cborData);
+    ASSERT_TRUE(result.has_value());
+    ASSERT_TRUE(result->credProps.has_value());
+    EXPECT_FALSE(result->credProps->rk);
+}
+
 } // namespace TestWebKitAPI
 
 #endif // ENABLE(WEB_AUTHN)