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

WebAuthn L3 Origin Binding and Cryptographic User-Verification Enforcement

Enforces strict canonical origin resolution, relying party ID matching, and cryptographic user-verification (UV) flag evaluation during WebAuthn assertion and registration ceremonies. Eliminates cross-origin passkey relay, phishing-proxy forwards, and session-fixation attacks by mandating tamper-proof clientDataJSON parsing and authenticatorData bit-flag checks against unforgeable server state.

Prohibited Anti-Pattern: Accepting Loose Origins or Missing Bit-Level User Verification Flags in WebAuthn Assertions

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: WebAuthn L3 Origin Binding and Cryptographic User-Verification Enforcement - Enforces strict canonical origin resolution, relying party ID matching, and cryptographic user-verification (UV) flag evaluation during WebAuthn assertion and registration ceremonies. Eliminates cross-origin passkey relay, phishing-proxy forwards, and session-fixation attacks by mandating tamper-proof clientDataJSON parsing and authenticatorData bit-flag checks against unforgeable server state.
globs: src/auth/**/*.{ts,js}, src/server/**/*.{ts,js}, lib/auth/**/*.{ts,js}, api/auth/**/*.{ts,js}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-l3-device-bound-origin-verification-standard"
---

# WebAuthn L3 Origin Binding and Cryptographic User-Verification Enforcement

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Accepting Loose Origins or Missing Bit-Level User Verification Flags in WebAuthn Assertions

## System Constraints
You are a Principal Security Architect enforcing the WebAuthn Level 3 (W3C Recommendation) authentication standard. You must ensure all WebAuthn registration and authentication ceremonies cryptographically validate exact clientDataJSON origins, reject partial or wildcard origin matches, enforce the expected Relying Party ID (rpId) SHA-256 hash match against authenticatorData, assert the User Verification (UV) bit-flag (0x04) when required, and strictly consume single-use cryptographic challenges.

## Strict Guidelines
- Engineers MUST ALWAYS validate clientDataJSON.origin against an explicit, immutable allowlist containing the exact scheme, fully qualified domain name, and port (e.g., https://login.example.com).
- Engineers MUST NOT use regex substrings, prefix matches, wildcard domains, or untrusted HTTP headers (e.g., X-Forwarded-Host) to determine or validate clientDataJSON.origin.
- Services MUST verify that the SHA-256 hash of the expected Relying Party ID (rpId) exactly equals the rpIdHash bytes (first 32 bytes) of authenticatorData.
- Services MUST assert the User Verification (UV) bit flag (Bit 2, 0x04) in authenticatorData when userVerification is set to 'required', rejecting responses that only present User Presence (UP, Bit 0, 0x01).
- Services MUST consume challenges atomically from server-side ephemeral storage (e.g., Redis with tight TTL) to guarantee challenges are strictly single-use and tamper-resistant.
- Components NEVER expose credentials or issue session tokens before all cryptographic assertion criteria (signature verification, counter validation, challenge matching, origin validation, and flag validation) pass.

## Bad vs Good Implementations
### WebAuthn Authentication Assertion Verification

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The code uses a permissive substring match on the origin (e.g., 'attacker-example.com' or 'example.com.attacker.com' would pass), fails to delete the challenge before verification creating a race window for replay attacks, ignores RP ID hash verification against authData, and verifies only User Presence instead of enforcing the User Verification (UV) flag.
```typescript
import { Request, Response } from 'express';

interface StoredChallenge {
  challenge: string;
}

const challengeStore = new Map<string, StoredChallenge>();

export async function verifyAssertion(req: Request, res: Response) {
  const { userId, clientDataJSON, authenticatorData } = req.body;
  
  const clientData = JSON.parse(Buffer.from(clientDataJSON, 'base64url').toString('utf-8'));
  const stored = challengeStore.get(userId);

  // CRITICAL FLAW: Loose origin regex check vulnerable to subdomain/phishing proxy takeover
  if (!clientData.origin.includes('example.com')) {
    return res.status(400).send('Invalid origin');
  }

  // CRITICAL FLAW: Challenge is not atomically removed before verification (replay hazard)
  if (clientData.challenge !== stored?.challenge) {
    return res.status(400).send('Challenge mismatch');
  }

  const authDataBuffer = Buffer.from(authenticatorData, 'base64url');
  const flags = authDataBuffer[32];

  // CRITICAL FLAW: Only checks User Presence (bit 0), ignoring User Verification requirement
  const userPresent = (flags & 0x01) !== 0;
  if (!userPresent) {
    return res.status(400).send('User not present');
  }

  return res.status(200).json({ success: true });
}
```

#### Production Standard (Correct)
> **Standard**: The production code enforces single-use challenge consumption using timing-safe comparisons, validates the exact canonical origin, confirms that the first 32 bytes of authenticatorData match the SHA-256 hash of the RP ID, and asserts both User Presence (0x01) and User Verification (0x04) flags.
```typescript
import crypto from 'node:crypto';
import { Request, Response } from 'express';

const EXPECTED_ORIGIN = 'https://auth.example.com';
const EXPECTED_RP_ID = 'example.com';
const EXPECTED_RP_ID_HASH = crypto.createHash('sha256').update(EXPECTED_RP_ID).digest();

interface ChallengeStore {
  consumeChallenge(userId: string): Promise<string | null>;
}
declare const sessionStore: ChallengeStore;

export async function verifyAssertion(req: Request, res: Response) {
  const { userId, clientDataJSON, authenticatorData } = req.body;

  // Invariant 1: Single-use challenge atomic retrieval and invalidation
  const expectedChallenge = await sessionStore.consumeChallenge(userId);
  if (!expectedChallenge) {
    return res.status(401).json({ error: 'Challenge expired or already consumed' });
  }

  // Invariant 2: Parse and strictly validate clientDataJSON
  const rawClientData = Buffer.from(clientDataJSON, 'base64url').toString('utf-8');
  const clientData = JSON.parse(rawClientData);

  if (clientData.type !== 'webauthn.get') {
    return res.status(400).json({ error: 'Invalid ceremony type' });
  }

  const challengeMatches = crypto.timingSafeEqual(
    Buffer.from(clientData.challenge),
    Buffer.from(expectedChallenge)
  );
  if (!challengeMatches) {
    return res.status(401).json({ error: 'Cryptographic challenge mismatch' });
  }

  // Invariant 3: Exact origin equality check (no regex, no prefix)
  if (clientData.origin !== EXPECTED_ORIGIN) {
    return res.status(403).json({ error: 'Origin mismatch: possible relay attack' });
  }

  // Invariant 4: Validate authenticatorData structure and flags
  const authDataBuffer = Buffer.from(authenticatorData, 'base64url');
  if (authDataBuffer.length < 37) {
    return res.status(400).json({ error: 'Malformed authenticatorData buffer' });
  }

  const rpIdHash = authDataBuffer.subarray(0, 32);
  if (!crypto.timingSafeEqual(rpIdHash, EXPECTED_RP_ID_HASH)) {
    return res.status(403).json({ error: 'Relying Party ID hash mismatch' });
  }

  const flags = authDataBuffer[32];
  const UP_FLAG = 0x01;
  const UV_FLAG = 0x04;

  // Enforce both User Presence (UP) and User Verification (UV)
  if ((flags & UP_FLAG) === 0 || (flags & UV_FLAG) === 0) {
    return res.status(403).json({ error: 'User verification failed: UP/UV bit missing' });
  }

  return res.status(200).json({ verified: true });
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: WebAuthn L3 Origin Binding and Cryptographic User-Verification Enforcement

WebAuthn L3 Origin Binding and Cryptographic User-Verification Enforcement defines an industrial-grade behavioral standard for security engineering. Enforces strict canonical origin resolution, relying party ID matching, and cryptographic user-verification (UV) flag evaluation during WebAuthn assertion and registration ceremonies. Eliminates cross-origin passkey relay, phishing-proxy forwards, and session-fixation attacks by mandating tamper-proof clientDataJSON parsing and authenticatorData bit-flag checks against unforgeable server state. 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 Loose Origins or Missing Bit-Level User Verification Flags in WebAuthn Assertions 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 Loose Origins or Missing Bit-Level User Verification Flags in WebAuthn AssertionsCritical
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 validate clientDataJSON.origin against an explicit, immutable allowlist containing the exact scheme, fully qualified domain name, and port (e.g., https

Engineers MUST ALWAYS validate clientDataJSON.origin against an explicit, immutable allowlist containing the exact scheme, fully qualified domain name, and port (e.g., https://login.example.com).

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 NOT use regex substrings, prefix matches, wildcard domains, or untrusted HTTP headers (e.g., X-Forwarded-Host) to determine or validate clientDataJSON.origin.

Engineers MUST NOT use regex substrings, prefix matches, wildcard domains, or untrusted HTTP headers (e.g., X-Forwarded-Host) to determine or validate clientDataJSON.origin.

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 that the SHA-256 hash of the expected Relying Party ID (rpId) exactly equals the rpIdHash bytes (first 32 bytes) of authenticatorData.

Services MUST verify that the SHA-256 hash of the expected Relying Party ID (rpId) exactly equals the rpIdHash bytes (first 32 bytes) of authenticatorData.

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

Services MUST assert the User Verification (UV) bit flag (Bit 2, 0x04) in authenticatorData when userVerification is set to 'required', rejecting responses that only present User Presence (UP, Bit 0, 0x01).

Services MUST assert the User Verification (UV) bit flag (Bit 2, 0x04) in authenticatorData when userVerification is set to 'required', rejecting responses that only present User Presence (UP, Bit 0, 0x01).

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 consume challenges atomically from server-side ephemeral storage (e.g., Redis with tight TTL) to guarantee challenges are strictly single-use and tamper-resistant.

Services MUST consume challenges atomically from server-side ephemeral storage (e.g., Redis with tight TTL) to guarantee challenges are strictly single-use and tamper-resistant.

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

Components NEVER expose credentials or issue session tokens before all cryptographic assertion criteria (signature verification, counter validation, challenge matching, origin validation, and flag validation) pass.

Components NEVER expose credentials or issue session tokens before all cryptographic assertion criteria (signature verification, counter validation, challenge matching, origin validation, and flag validation) pass.

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 L3 Origin Binding and Cryptographic User-Verification Enforcement critical for AI coding assistants?

Enforces strict canonical origin resolution, relying party ID matching, and cryptographic user-verification (UV) flag evaluation during WebAuthn assertion and registration ceremonies. Eliminates cross-origin passkey relay, phishing-proxy forwards, and session-fixation attacks by mandating tamper-proof clientDataJSON parsing and authenticatorData bit-flag checks against unforgeable server state. 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 Loose Origins or Missing Bit-Level User Verification Flags in WebAuthn Assertions) 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