This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: webauthn-l3-syncable-passkey-attestation-standard

WebAuthn Level 3 Syncable Passkey Authenticator-Bound Attestation Standard

Enforces strict WebAuthn Level 3 cryptographic verification semantics for both hardware-bound and multi-device syncable passkeys. Mandates atomic single-use challenge consumption, exact clientDataHash reconstruction, bitwise authenticatorData flag validation (UP, UV, BE, BS), and transport-aware replay protection.

Prohibited Anti-Pattern: Accepting unhashed clientData, bypassing UP/UV flags, or enforcing monotonic signCount on syncable passkeys

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: WebAuthn Level 3 Syncable Passkey Authenticator-Bound Attestation Standard - Enforces strict WebAuthn Level 3 cryptographic verification semantics for both hardware-bound and multi-device syncable passkeys. Mandates atomic single-use challenge consumption, exact clientDataHash reconstruction, bitwise authenticatorData flag validation (UP, UV, BE, BS), and transport-aware replay protection.
globs: src/**/auth/**/*.{ts,tsx}, src/**/passkey/**/*.{ts,tsx}, src/**/webauthn/**/*.{ts,tsx}, packages/**/auth/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-l3-syncable-passkey-attestation-standard"
---

# WebAuthn Level 3 Syncable Passkey Authenticator-Bound Attestation Standard

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Accepting unhashed clientData, bypassing UP/UV flags, or enforcing monotonic signCount on syncable passkeys

## System Constraints
You are a Principal Security Architect enforcing the WebAuthn Level 3 Authenticator-Bound and Syncable Passkey Verification Standard. Multi-device syncable credentials (backed by ecosystems like iCloud Keychain or Google Password Manager) inherently violate traditional FIDO monotonic counter guarantees while introducing multi-device sync replay vulnerabilities. You MUST mandate byte-level verification of clientDataHash, bitwise flag analysis for User Presence (UP), User Verification (UV), Backup Eligibility (BE), and Backup State (BS), constant-time challenge invalidation, and strict crypto-suite validation.

## Strict Guidelines
- Engineers MUST ALWAYS compute the SHA-256 hash of raw `clientDataJSON` to produce `clientDataHash` and verify the cryptographic signature over the binary concatenation of `authData || clientDataHash`.
- Engineers MUST ALWAYS atomically consume and invalidate the cryptographic challenge in a single-use distributed cache before verifying the signature to prevent replay attacks.
- Services MUST verify bitwise flags in `authData`: bit 0 (User Presence - UP) MUST be 1, and bit 2 (User Verification - UV) MUST be 1 for passkey authentication requiring biometric or PIN confirmation.
- Engineers MUST NOT enforce strictly increasing `signCount` checking when `flags.backupEligibility` (bit 3) is true, as multi-device syncable passkeys legitimately yield `signCount = 0` or non-sequential counters across synchronized nodes.
- Services MUST enforce strict monotonic increment (`signCount > storedSignCount`) IF AND ONLY IF the credential is verified as device-bound (`flags.backupEligibility === false`).
- Engineers MUST ALWAYS verify that `clientData.origin` exactly matches the expected canonical origin (including protocol and port) and verify `clientData.type` strictly matches `'webauthn.get'` or `'webauthn.create'`.
- Code SHOULD verify the COSE algorithm identifiers and reject non-approved algorithms, restricting public keys to approved suites (e.g., ES256 / COSE -7, Ed25519 / COSE -8, RS256 / COSE -257).

## Bad vs Good Implementations
### WebAuthn L3 Assertion Verification with Flag & Counter Branching

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The bad implementation compares challenges insecurely without atomic one-time consumption, fails to compute the SHA-256 clientDataHash over clientDataJSON, ignores User Presence (UP) and User Verification (UV) flags in authenticatorData, and indiscriminately rejects syncable passkeys whose signCount is static (0).
```typescript
import crypto from 'node:crypto';

interface AssertionRecord {
  rawId: string;
  response: {
    clientDataJSON: string;
    authenticatorData: string;
    signature: string;
  };
}

export async function verifyAssertionBad(
  assertion: AssertionRecord,
  expectedChallenge: string,
  storedSignCount: number
): Promise<boolean> {
  // VULNERABILITY 1: Plain JSON decode without constant-time challenge comparison or single-use consumption
  const clientData = JSON.parse(Buffer.from(assertion.response.clientDataJSON, 'base64url').toString('utf8'));
  if (clientData.challenge !== expectedChallenge) {
    return false;
  }

  // VULNERABILITY 2: Monotonic counter enforced globally; breaks all syncable passkeys (iCloud, Google)
  const authDataBuffer = Buffer.from(assertion.response.authenticatorData, 'base64url');
  const signCount = authDataBuffer.readUInt32BE(33);
  if (signCount <= storedSignCount) {
    throw new Error('Clone detected or counter rewind');
  }

  // VULNERABILITY 3: Missing UP and UV bitwise flag validation
  // VULNERABILITY 4: Passing raw clientDataJSON instead of authData || sha256(clientDataJSON)
  return true;
}
```

#### Production Standard (Correct)
> **Standard**: Implements full WebAuthn Level 3 zero-trust semantics: atomically consumes the challenge to neutralize replay attacks, enforces constant-time comparison, validates User Presence (bit 0) and User Verification (bit 2), reconstructs signed payload using `authData || sha256(clientDataJSON)`, and branches signCount verification based on Backup Eligibility (BE) and Backup State (BS) flags.
```typescript
import crypto from 'node:crypto';

interface AssertionPayload {
  rawId: string;
  response: {
    clientDataJSON: string;      // Base64URL
    authenticatorData: string;   // Base64URL
    signature: string;           // Base64URL
    userHandle?: string;         // Base64URL
  };
}

interface StoredCredential {
  publicKeyPem: string;
  signCount: number;
  isSyncable: boolean;
}

interface ChallengeStore {
  consumeChallenge(challenge: string): Promise<boolean>;
}

export async function verifyAssertionL3(
  payload: AssertionPayload,
  expectedOrigin: string,
  expectedChallenge: string,
  storedCred: StoredCredential,
  challengeStore: ChallengeStore
): Promise<{ verified: boolean; newSignCount: number }> {
  // 1. Atomic single-use challenge consumption
  const isChallengeValid = await challengeStore.consumeChallenge(expectedChallenge);
  if (!isChallengeValid) {
    throw new Error('SECURITY_ERROR: Challenge expired or replayed');
  }

  // 2. Parse and validate clientDataJSON
  const clientDataBytes = Buffer.from(payload.response.clientDataJSON, 'base64url');
  const clientData = JSON.parse(clientDataBytes.toString('utf8'));

  if (clientData.type !== 'webauthn.get') {
    throw new Error('SECURITY_ERROR: Invalid clientData type');
  }

  const receivedChallengeBuf = Buffer.from(clientData.challenge, 'utf8');
  const expectedChallengeBuf = Buffer.from(expectedChallenge, 'utf8');
  if (
    receivedChallengeBuf.length !== expectedChallengeBuf.length ||
    !crypto.timingSafeEqual(receivedChallengeBuf, expectedChallengeBuf)
  ) {
    throw new Error('SECURITY_ERROR: Challenge mismatch');
  }

  if (clientData.origin !== expectedOrigin) {
    throw new Error('SECURITY_ERROR: Origin mismatch');
  }

  // 3. Compute clientDataHash = SHA-256(clientDataJSON)
  const clientDataHash = crypto.createHash('sha256').update(clientDataBytes).digest();

  // 4. Parse authenticatorData bit flags
  const authDataBuf = Buffer.from(payload.response.authenticatorData, 'base64url');
  if (authDataBuf.length < 37) {
    throw new Error('SECURITY_ERROR: Truncated authenticatorData');
  }

  const flags = authDataBuf.readUInt8(32);
  const up = (flags & 0x01) !== 0; // Bit 0: User Present
  const uv = (flags & 0x04) !== 0; // Bit 2: User Verified
  const be = (flags & 0x08) !== 0; // Bit 3: Backup Eligibility
  const bs = (flags & 0x10) !== 0; // Bit 4: Backup State

  if (!up) {
    throw new Error('SECURITY_ERROR: User presence (UP) not asserted');
  }
  if (!uv) {
    throw new Error('SECURITY_ERROR: User verification (UV) required but not asserted');
  }

  // 5. Inspect signCount handling based on syncable credential state (Level 3 spec)
  const currentSignCount = authDataBuf.readUInt32BE(33);
  if (!be && !bs) {
    // Hardware-bound / single-device credential: enforce strict monotonic increment
    if (currentSignCount > 0 && currentSignCount <= storedCred.signCount) {
      throw new Error('SECURITY_ERROR: Monotonic counter rewind on device-bound key');
    }
  } else {
    // Syncable passkey: signCount is typically 0 or non-monotonic across synchronized devices
    // Invariant: Do not enforce strict monotonicity, but track state transitions
  }

  // 6. Verify signature over concatenation: authData || sha256(clientDataJSON)
  const signature = Buffer.from(payload.response.signature, 'base64url');
  const signedData = Buffer.concat([authDataBuf, clientDataHash]);

  const verifier = crypto.createVerify('SHA256');
  verifier.update(signedData);
  const isSignatureValid = verifier.verify(storedCred.publicKeyPem, signature);

  if (!isSignatureValid) {
    throw new Error('SECURITY_ERROR: Passkey signature verification failed');
  }

  return {
    verified: true,
    newSignCount: currentSignCount
  };
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: WebAuthn Level 3 Syncable Passkey Authenticator-Bound Attestation Standard

WebAuthn Level 3 Syncable Passkey Authenticator-Bound Attestation Standard defines an industrial-grade behavioral standard for security engineering. Enforces strict WebAuthn Level 3 cryptographic verification semantics for both hardware-bound and multi-device syncable passkeys. Mandates atomic single-use challenge consumption, exact clientDataHash reconstruction, bitwise authenticatorData flag validation (UP, UV, BE, BS), and transport-aware replay protection. Modern software architectures require strict adherence to deterministic patterns to guarantee high availability, maintainability, and zero security vulnerabilities.

Framework Paradigm Shift & Drift MechanicsLLMs are trained on millions of open-source repositories containing outdated code, legacy idioms, and unpatched antipatterns. When coding assistants generate implementations for this stack, they default to common statistical tokens: Accepting unhashed clientData, bypassing UP/UV flags, or enforcing monotonic signCount on syncable passkeys Without an explicit system instruction file, developers spend hours debugging silent failures.
Failure Modes & Production Blast Radius

Hazard Analysis: What Breaks Without This Rule

The following failure modes have been cataloged from hundreds of hours of production code reviews where AI assistants produced non-compliant implementations:

Failure ModeAI Symptom (The Anti-Pattern)SeverityProduction Impact & Remedy
AI Hallucination & Deprecation DriftAccepting unhashed clientData, bypassing UP/UV flags, or enforcing monotonic signCount on syncable passkeysCritical
Violating this industrial standard introduces regression bugs, security risks, and unexpected runtime failures in production.
Enforce explicit behavioral system directives across all AI coding assistants in your repository.
Silent Architecture InconsistencyAI assistants produce mixed paradigms across files, creating fragmented codebase conventions.Medium
Increases cognitive load during code reviews and leads to maintenance debt across engineering teams.
Pin project conventions in .cursor/rules, CLAUDE.md, and AGENTS.md so all team agents follow identical guardrails.
Architectural Directives in Detail

Step-by-Step Production Directives

Each rule constraint below is injected into the AI agent's system prompt to establish deterministic boundaries:

1

Engineers MUST ALWAYS compute the SHA-256 hash of raw `clientDataJSON` to produce `clientDataHash` and verify the cryptographic signature over the binary concatenation of `authData || clientDataHash`.

Engineers MUST ALWAYS compute the SHA-256 hash of raw `clientDataJSON` to produce `clientDataHash` and verify the cryptographic signature over the binary concatenation of `authData || clientDataHash`.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
2

Engineers MUST ALWAYS atomically consume and invalidate the cryptographic challenge in a single-use distributed cache before verifying the signature to prevent replay attacks.

Engineers MUST ALWAYS atomically consume and invalidate the cryptographic challenge in a single-use distributed cache before verifying the signature to prevent replay attacks.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
3

Services MUST verify bitwise flags in `authData`

Services MUST verify bitwise flags in `authData`: bit 0 (User Presence - UP) MUST be 1, and bit 2 (User Verification - UV) MUST be 1 for passkey authentication requiring biometric or PIN confirmation.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
4

Engineers MUST NOT enforce strictly increasing `signCount` checking when `flags.backupEligibility` (bit 3) is true, as multi-device syncable passkeys legitimately yield `signCount = 0` or non-sequential counters across synchronized nodes.

Engineers MUST NOT enforce strictly increasing `signCount` checking when `flags.backupEligibility` (bit 3) is true, as multi-device syncable passkeys legitimately yield `signCount = 0` or non-sequential counters across synchronized nodes.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
5

Services MUST enforce strict monotonic increment (`signCount > storedSignCount`) IF AND ONLY IF the credential is verified as device-bound (`flags.backupEligibility === false`).

Services MUST enforce strict monotonic increment (`signCount > storedSignCount`) IF AND ONLY IF the credential is verified as device-bound (`flags.backupEligibility === false`).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
6

Engineers MUST ALWAYS verify that `clientData.origin` exactly matches the expected canonical origin (including protocol and port) and verify `clientData.type` strictly matches `'webauthn.get'` or `'webauthn.create'`.

Engineers MUST ALWAYS verify that `clientData.origin` exactly matches the expected canonical origin (including protocol and port) and verify `clientData.type` strictly matches `'webauthn.get'` or `'webauthn.create'`.

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
7

Code SHOULD verify the COSE algorithm identifiers and reject non-approved algorithms, restricting public keys to approved suites (e.g., ES256 / COSE -7, Ed25519 / COSE -8, RS256 / COSE -257).

Code SHOULD verify the COSE algorithm identifiers and reject non-approved algorithms, restricting public keys to approved suites (e.g., ES256 / COSE -7, Ed25519 / COSE -8, RS256 / COSE -257).

Rationale:AI models frequently generate unconstrained code here because statistical language distributions lack project-specific architectural context. Mandating this directive ensures that generated code adheres to verified industrial production requirements.
Enforcement:Integrated into the Agent Pack rule file. When Cursor, Claude Code, or Codex processes this prompt, it applies this constraint before emitting syntax.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is WebAuthn Level 3 Syncable Passkey Authenticator-Bound Attestation Standard critical for AI coding assistants?

Enforces strict WebAuthn Level 3 cryptographic verification semantics for both hardware-bound and multi-device syncable passkeys. Mandates atomic single-use challenge consumption, exact clientDataHash reconstruction, bitwise authenticatorData flag validation (UP, UV, BE, BS), and transport-aware replay protection. Without explicit behavioral boundaries, AI coding assistants (Cursor, Claude Code, Windsurf, Codex) rely on training data averages, which frequently produce deprecated, inefficient, or vulnerable code patterns.

Q:How does adopting this rule prevent AI hallucinations?

This rule explicitly declares what the AI must avoid (Accepting unhashed clientData, bypassing UP/UV flags, or enforcing monotonic signCount on syncable passkeys) and prescribes verified positive examples. Grounding the LLM with negative and positive pairs eliminates guesswork.

Q:Which AI coding environments are supported?

This specification is multi-platform compatible: Cursor (.cursor/rules/*.mdc & .cursorrules), Anthropic Claude Code (CLAUDE.md), Windsurf (.windsurfrules), Codex / Cline (AGENTS.md), and GitHub Copilot (.github/copilot-instructions.md).

Q:Can I combine this rule with other technology stacks?

Yes. Use the Interactive Stack Builder or download an Agent Pack to merge this rule with other frontend, backend, database, security, and DevOps rules without syntax collision.

Open Specification · CC BY 4.0·Free for Personal, Team & Commercial In-Repo Use

Citation & Open Source Attribution Guidelines

This specification is licensed under Creative Commons Attribution 4.0 International (CC BY 4.0). You are completely free to adapt and share this rule in your workspace. If citing, including in public AI benchmark datasets, or redistributing, attribution to AgentRules.org is required.

1 Rule in Stack

WebAuthn