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

WebAuthn Conditional UI Device-Bound Assertion & Relay Protection Standard

Enforces origin-bound, hardware-backed cryptographic validation for WebAuthn Conditional UI (autofill) ceremonies to neutralize passkey relay attacks and session spoofing. Mandates cryptographically random server challenges bound to ephemeral sessions, mandatory User Verification and User Presence flag checks, validation of non-exportable hardware flags, and deterministic AbortController lifecycle management.

Prohibited Anti-Pattern: Permissive Conditional UI Autofill Permitting Synced Multi-Device Credentials and Unverified Relay Assertions

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: WebAuthn Conditional UI Device-Bound Assertion & Relay Protection Standard - Enforces origin-bound, hardware-backed cryptographic validation for WebAuthn Conditional UI (autofill) ceremonies to neutralize passkey relay attacks and session spoofing. Mandates cryptographically random server challenges bound to ephemeral sessions, mandatory User Verification and User Presence flag checks, validation of non-exportable hardware flags, and deterministic AbortController lifecycle management.
globs: src/auth/**/*.{ts,tsx}, src/server/auth/**/*.{ts,tsx}, src/pages/api/auth/**/*.{ts,tsx}, src/lib/auth/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-conditional-ui-device-bound-assertion-standard"
---

# WebAuthn Conditional UI Device-Bound Assertion & Relay Protection Standard

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Permissive Conditional UI Autofill Permitting Synced Multi-Device Credentials and Unverified Relay Assertions

## System Constraints
You are a Principal Security Architect enforcing the WebAuthn Conditional UI Device-Bound Assertion Standard. You MUST mandate that all WebAuthn Conditional UI workflows enforce origin-bound verification, strict ephemeral challenge checks, platform authenticator binding, and hardware security flags (UP, UV, and non-backed-up state when device-bound assertions are specified).

## Strict Guidelines
- Engineers MUST ALWAYS verify that clientDataJSON.type is 'webauthn.get' and clientDataJSON.origin exactly matches the expected fully qualified domain and scheme (HTTPS).
- Engineers MUST ALWAYS validate that the server-side challenge is single-use, bound to the ephemeral session cookie, and expires within at most 60 seconds.
- Engineers MUST inspect authenticatorData bit flags to verify User Present (UP, bit 0) and User Verified (UV, bit 2) are both set to 1.
- Services MUST verify device-bound credential constraints by confirming the Backup State (BS, bit 3) flag is 0 and rejecting multi-device synced passkeys when device-bound platform security is strictly required.
- Components MUST ALWAYS wire an AbortController signal to navigator.credentials.get with mediation: 'conditional' and clean up listeners on component unmount to prevent race conditions and credential leaks.
- Engineers MUST NOT accept base64url challenge tokens from the client request body; the challenge MUST be resolved strictly from authenticated server-side session state.
- Engineers MUST NOT configure userVerification as 'discouraged' or 'preferred'; it MUST ALWAYS be set to 'required' for high-assurance device-bound authentication.

## Bad vs Good Implementations
### Verifying WebAuthn Conditional UI Assertion with Device-Bound Invariants

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The handler accepts a client-provided challenge rather than fetching it from server session state, ignores origin validation allowing cross-origin replay, fails to cryptographically verify the signature, and skips checking the authenticatorData flags (User Presence, User Verification, and Backup State).
```typescript
import { Request, Response } from 'express';

// ANTI-PATTERN: Blindly trusts client-provided challenge, ignores hardware flags,
// permits synced passkeys when device-bound hardware isolation is required,
// and does not enforce origin or user verification flags.
export async function verifyConditionalAssertion(req: Request, res: Response) {
  const { credential, clientChallenge } = req.body;

  // Flaw 1: Validating against client-supplied challenge instead of session
  const clientData = JSON.parse(Buffer.from(credential.response.clientDataJSON, 'base64url').toString('utf8'));
  if (clientData.challenge !== clientChallenge) {
    return res.status(401).json({ error: 'Challenge mismatch' });
  }

  // Flaw 2: Missing origin check against server configuration
  // Flaw 3: Authenticator data flags (UP, UV, BS) completely ignored
  const authDataBuffer = Buffer.from(credential.response.authenticatorData, 'base64url');
  
  // Insecure session creation without verifying signature or hardware binding
  req.session.userId = credential.id;
  return res.json({ success: true });
}
```

#### Production Standard (Correct)
> **Standard**: Implements strict validation: enforces server-side single-use challenge expiration, checks origin and RP ID hash using timing-safe comparisons, and verifies authenticatorData flags requiring User Present (UP), User Verified (UV), and Backup State (BS=0) to guarantee a hardware-isolated, device-bound credential.
```typescript
import { Request, Response } from 'express';
import crypto from 'node:crypto';

interface StoredAuthSession {
  expectedChallenge: string;
  challengeCreatedAt: number;
  userId: string;
}

const EXPECTED_ORIGIN = 'https://auth.company.internal';
const EXPECTED_RP_ID = 'company.internal';
const CHALLENGE_TTL_MS = 60_000;

export async function verifyDeviceBoundConditionalAssertion(req: Request, res: Response) {
  const session = req.session.authSession as StoredAuthSession | undefined;
  if (!session || Date.now() - session.challengeCreatedAt > CHALLENGE_TTL_MS) {
    return res.status(401).json({ error: 'Authentication challenge expired or missing' });
  }

  // Consume challenge immediately to prevent replay
  const expectedChallenge = session.expectedChallenge;
  delete req.session.authSession;

  const { credential } = req.body;
  if (!credential?.response?.clientDataJSON || !credential?.response?.authenticatorData) {
    return res.status(400).json({ error: 'Malformed assertion payload' });
  }

  // 1. Validate clientDataJSON
  const clientData = JSON.parse(Buffer.from(credential.response.clientDataJSON, 'base64url').toString('utf8'));
  if (clientData.type !== 'webauthn.get') {
    return res.status(400).json({ error: 'Invalid clientData type' });
  }
  if (clientData.origin !== EXPECTED_ORIGIN) {
    return res.status(403).json({ error: 'Origin mismatch violation' });
  }
  if (!crypto.timingSafeEqual(Buffer.from(clientData.challenge), Buffer.from(expectedChallenge))) {
    return res.status(401).json({ error: 'Cryptographic challenge failed' });
  }

  // 2. Validate authenticatorData flags for device-bound hardware isolation
  const authData = Buffer.from(credential.response.authenticatorData, 'base64url');
  if (authData.length < 37) {
    return res.status(400).json({ error: 'Invalid authenticatorData length' });
  }

  const rpIdHash = authData.subarray(0, 32);
  const expectedRpIdHash = crypto.createHash('sha256').update(EXPECTED_RP_ID).digest();
  if (!crypto.timingSafeEqual(rpIdHash, expectedRpIdHash)) {
    return res.status(403).json({ error: 'RP ID hash mismatch' });
  }

  const flags = authData[32];
  const userPresent = (flags & 0x01) !== 0;
  const userVerified = (flags & 0x04) !== 0;
  const backupState = (flags & 0x08) !== 0; // Bit 3: 0 = not backed up (device-bound)

  if (!userPresent || !userVerified) {
    return res.status(401).json({ error: 'Hardware User Presence and User Verification required' });
  }

  // Enforce hardware device-bound assertion (reject synced passkeys)
  if (backupState) {
    return res.status(403).json({ error: 'Multi-device synced passkeys rejected: TPM/Secure Enclave hardware binding required' });
  }

  // Proceed to cryptographic public key signature verification over (authData || clientDataHash)
  // ...
  return res.json({ verified: true });
}
```

Recommended MCP Servers (mcp-serverlist.com)

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

Architectural Specification & Invariant Rationale

Architectural Invariant Design: WebAuthn Conditional UI Device-Bound Assertion & Relay Protection Standard

WebAuthn Conditional UI Device-Bound Assertion & Relay Protection Standard defines an industrial-grade behavioral standard for security engineering. Enforces origin-bound, hardware-backed cryptographic validation for WebAuthn Conditional UI (autofill) ceremonies to neutralize passkey relay attacks and session spoofing. Mandates cryptographically random server challenges bound to ephemeral sessions, mandatory User Verification and User Presence flag checks, validation of non-exportable hardware flags, and deterministic AbortController lifecycle management. 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: Permissive Conditional UI Autofill Permitting Synced Multi-Device Credentials and Unverified Relay 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 DriftPermissive Conditional UI Autofill Permitting Synced Multi-Device Credentials and Unverified Relay 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 verify that clientDataJSON.type is 'webauthn.get' and clientDataJSON.origin exactly matches the expected fully qualified domain and scheme (HTTPS).

Engineers MUST ALWAYS verify that clientDataJSON.type is 'webauthn.get' and clientDataJSON.origin exactly matches the expected fully qualified domain and scheme (HTTPS).

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 validate that the server-side challenge is single-use, bound to the ephemeral session cookie, and expires within at most 60 seconds.

Engineers MUST ALWAYS validate that the server-side challenge is single-use, bound to the ephemeral session cookie, and expires within at most 60 seconds.

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

Engineers MUST inspect authenticatorData bit flags to verify User Present (UP, bit 0) and User Verified (UV, bit 2) are both set to 1.

Engineers MUST inspect authenticatorData bit flags to verify User Present (UP, bit 0) and User Verified (UV, bit 2) are both set to 1.

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 verify device-bound credential constraints by confirming the Backup State (BS, bit 3) flag is 0 and rejecting multi-device synced passkeys when device-bound platform security is strictly required.

Services MUST verify device-bound credential constraints by confirming the Backup State (BS, bit 3) flag is 0 and rejecting multi-device synced passkeys when device-bound platform security is strictly required.

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

Components MUST ALWAYS wire an AbortController signal to navigator.credentials.get with mediation

Components MUST ALWAYS wire an AbortController signal to navigator.credentials.get with mediation: 'conditional' and clean up listeners on component unmount to prevent race conditions and credential leaks.

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 NOT accept base64url challenge tokens from the client request body

Engineers MUST NOT accept base64url challenge tokens from the client request body; the challenge MUST be resolved strictly from authenticated server-side session state.

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

Engineers MUST NOT configure userVerification as 'discouraged' or 'preferred'

Engineers MUST NOT configure userVerification as 'discouraged' or 'preferred'; it MUST ALWAYS be set to 'required' for high-assurance device-bound authentication.

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 Conditional UI Device-Bound Assertion & Relay Protection Standard critical for AI coding assistants?

Enforces origin-bound, hardware-backed cryptographic validation for WebAuthn Conditional UI (autofill) ceremonies to neutralize passkey relay attacks and session spoofing. Mandates cryptographically random server challenges bound to ephemeral sessions, mandatory User Verification and User Presence flag checks, validation of non-exportable hardware flags, and deterministic AbortController lifecycle management. 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 (Permissive Conditional UI Autofill Permitting Synced Multi-Device Credentials and Unverified Relay 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