GHSA-6hxq-p678-4hr2

Updated on 04 Sep 2026

Severity

Awaiting Analysis

Details

Overview

About vulnerability

Summary

validateCertificatePath() does not verify that an attestation’s certificate chain actually terminates at a configured trust anchor. When walking the chain it stops at the first self-signed certificate it finds (which could be user-supplied), and exits early.

This happens before the configured Apple/Google/etc trust anchor (which is concatenated to the end of the chain) is reached.

A user can therefore register a credential and have the server accept it as if it were backed by a genuine Apple / Android SafetyNet / Yubikey / etc.

Details

packages/server/src/helpers/validateCertificatePath.ts:

The configured trust anchor is appended to the end of the untrusted chain (line 83):

const x5cWithTrustAnchor = x5cCertsParsed.concat([anchor]);

The walk then verifies each cert was signed by the next, but breaks on the first self-signed cert (lines 104–116):

if (issuer.subject === issuer.issuer) {
// Root cert detected, make sure it signed itself
const issuerSignedIssuer = await issuer.verify(
{ publicKey: issuer.publicKey, signatureOnly: true },
WebCrypto,
);
if (!issuerSignedIssuer) {
throw new InvalidSubjectAndIssuer();
}
break;   // <-- exits before the appended trust anchor is ever checked if user supplied self-signed cert comes first
}

The success condition is therefore “the certs form an internally-consistent chain ending in some self-signed cert” Rather than “the chain terminates at one of the configured trust anchors.”

Exploit shape

attacker sends:  x5c = [ forgedLeaf (signed by attacker root),
attackerSelfSignedRoot ]

library builds:  [ forgedLeaf, attackerSelfSignedRoot, <configured Apple/Google/etc root> ]

walk:  forgedLeaf -> attackerSelfSignedRoot        (verifies, attacker controls both)
attackerSelfSignedRoot is self-signed        -> break
attackerSelfSignedRoot -> configured root    (NEVER CHECKED)

return true. The configured anchor never gets checked.

As far as observed, all attestation enforcement uses validateCertificatePath when using MDS etc.

Details

Affected product:
simplewebauthn
Affected packages:
@simplewebauthn/server @ 9.0.3