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

WebAuthn Origin Lockout & Top-Level Context Enforcement Standard

Enforces cryptographic origin validation and strict Relying Party ID (RP-ID) verification against raw clientDataJSON on the authentication server, coupled with strict Permissions-Policy iframe exclusion. Prevents reverse-proxy Adversary-in-the-Middle (AitM) phishing frameworks from capturing or relaying passkey ceremonies across spoofed or sub-framed origins.

Prohibited Anti-Pattern: Lenient origin parsing, regex suffix matching, or trusting client headers during WebAuthn assertion verification.

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: WebAuthn Origin Lockout & Top-Level Context Enforcement Standard - Enforces cryptographic origin validation and strict Relying Party ID (RP-ID) verification against raw clientDataJSON on the authentication server, coupled with strict Permissions-Policy iframe exclusion. Prevents reverse-proxy Adversary-in-the-Middle (AitM) phishing frameworks from capturing or relaying passkey ceremonies across spoofed or sub-framed origins.
globs: src/auth/**/*.{ts,tsx,js,jsx}, src/server/auth/**/*.{ts,js}, src/api/auth/**/*.{ts,js}, src/middleware/**/*.{ts,js}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-device-bound-origin-lockout-guardrail"
---

# WebAuthn Origin Lockout & Top-Level Context Enforcement Standard

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Lenient origin parsing, regex suffix matching, or trusting client headers during WebAuthn assertion verification.

## System Constraints
You are a Principal Security Architect enforcing the WebAuthn Device-Bound Passkey Origin Lockout Guardrail. Mandate exact-match byte-level validation of clientDataJSON origin and RP-ID, forbid dynamic origin derivation from untrusted HTTP headers, and enforce explicit cross-origin iframe delegation policies.

## Strict Guidelines
- Engineers MUST ALWAYS enforce strict, canonical string equality checks between the clientDataJSON.origin and an immutable, server-configured allowlist of fully qualified origins (protocol, domain, port).
- Engineers MUST NOT construct the expected RP-ID, Origin, or Challenge dynamically from incoming client HTTP request headers (such as Host, X-Forwarded-Host, or Referer).
- Services MUST verify clientDataJSON.type strictly matches 'webauthn.get' for authentication assertions and 'webauthn.create' for registration ceremonies.
- Services MUST enforce cryptographic challenge matching in constant time and invalidate session challenges immediately upon receipt, regardless of ceremony success or failure.
- Components NEVER execute WebAuthn ceremonies inside embedded frames unless the parent document explicitly grants permission via 'Permissions-Policy: publickey-credentials-get=(self)'.
- Frontend authentication handlers MUST verify 'window === window.top' before invoking navigator.credentials.get/create unless explicitly isolated and designated by policy.

## Bad vs Good Implementations
### WebAuthn Assertion Verification Origin Check

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Derives the expected origin from mutable client headers (Host / X-Forwarded-Host) and uses lenient substring checking (`endsWith`). A reverse-proxy phishing setup (like Evilginx) can pass this check by proxying the request and spoofing matching subdomains or header states.
```typescript
import { Request, Response } from 'express';

interface ClientDataJSON {
  type: string;
  challenge: string;
  origin: string;
}

export async function verifyAssertion(req: Request, res: Response) {
  const { clientDataJSONBase64, expectedChallenge } = req.body;
  const rawJson = Buffer.from(clientDataJSONBase64, 'base64url').toString('utf-8');
  const clientData: ClientDataJSON = JSON.parse(rawJson);

  // VULNERABLE: Derives expected origin dynamically from request headers
  const host = req.headers['x-forwarded-host'] || req.headers.host;
  
  // VULNERABLE: Loose substring/suffix matching susceptible to reverse-proxy AitM spoofing
  if (!clientData.origin.endsWith(host as string)) {
    return res.status(403).json({ error: 'Origin mismatch' });
  }

  // VULNERABLE: Non-constant time challenge verification
  if (clientData.challenge !== expectedChallenge) {
    return res.status(401).json({ error: 'Invalid challenge' });
  }

  return res.status(200).json({ status: 'authenticated' });
}
```

#### Production Standard (Correct)
> **Standard**: Enforces strict canonical allowlist matching of clientDataJSON.origin, blocks cross-origin assertions (crossOrigin === true), verifies ceremony type, validates challenges in constant time, and consumes single-use session tokens.
```typescript
import { Request, Response } from 'express';
import crypto from 'node:crypto';

// Canonical server-side configuration invariant; NEVER derived from client headers
const EXPECTED_ORIGINS = new Set<string>([
  'https://auth.company.internal',
  'https://login.company.com'
]);
const EXPECTED_RP_ID = 'company.com';

interface ClientDataJSON {
  type: string;
  challenge: string;
  origin: string;
  crossOrigin?: boolean;
}

export async function verifyAssertion(req: Request, res: Response) {
  const session = req.session;
  const expectedChallenge = session?.webauthnChallenge;
  
  // Always consume challenge immediately to prevent replay attacks
  if (session) {
    delete session.webauthnChallenge;
  }

  if (!expectedChallenge) {
    return res.status(400).json({ error: 'Missing or expired ceremony challenge' });
  }

  const { clientDataJSONBase64 } = req.body;
  if (typeof clientDataJSONBase64 !== 'string') {
    return res.status(400).json({ error: 'Invalid payload structure' });
  }

  const rawJson = Buffer.from(clientDataJSONBase64, 'base64url').toString('utf-8');
  const clientData: ClientDataJSON = JSON.parse(rawJson);

  // INVARIANT 1: Ceremony Type Lock
  if (clientData.type !== 'webauthn.get') {
    return res.status(403).json({ error: 'Unexpected client data ceremony type' });
  }

  // INVARIANT 2: Exact Origin Match Against Immutable Allowlist
  if (!EXPECTED_ORIGINS.has(clientData.origin)) {
    return res.status(403).json({ error: 'Origin unauthorized for credential assertion' });
  }

  // INVARIANT 3: Cross-Origin Delegation Lockout
  if (clientData.crossOrigin === true) {
    return res.status(403).json({ error: 'Cross-origin passkey ceremonies are disallowed' });
  }

  // INVARIANT 4: Constant-Time Challenge Verification
  const challengeBuffer = Buffer.from(clientData.challenge, 'base64url');
  const expectedBuffer = Buffer.from(expectedChallenge, 'base64url');

  if (
    challengeBuffer.length !== expectedBuffer.length ||
    !crypto.timingSafeEqual(challengeBuffer, expectedBuffer)
  ) {
    return res.status(401).json({ error: 'Cryptographic challenge verification failed' });
  }

  return res.status(200).json({ status: 'authenticated' });
}
```

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 Origin Lockout & Top-Level Context Enforcement Standard

WebAuthn Origin Lockout & Top-Level Context Enforcement Standard defines an industrial-grade behavioral standard for security engineering. Enforces cryptographic origin validation and strict Relying Party ID (RP-ID) verification against raw clientDataJSON on the authentication server, coupled with strict Permissions-Policy iframe exclusion. Prevents reverse-proxy Adversary-in-the-Middle (AitM) phishing frameworks from capturing or relaying passkey ceremonies across spoofed or sub-framed origins. 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: Lenient origin parsing, regex suffix matching, or trusting client headers during WebAuthn assertion verification. 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 DriftLenient origin parsing, regex suffix matching, or trusting client headers during WebAuthn assertion verification.Critical
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 enforce strict, canonical string equality checks between the clientDataJSON.origin and an immutable, server-configured allowlist of fully qualified origins (protocol, domain, port).

Engineers MUST ALWAYS enforce strict, canonical string equality checks between the clientDataJSON.origin and an immutable, server-configured allowlist of fully qualified origins (protocol, domain, port).

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 construct the expected RP-ID, Origin, or Challenge dynamically from incoming client HTTP request headers (such as Host, X-Forwarded-Host, or Referer).

Engineers MUST NOT construct the expected RP-ID, Origin, or Challenge dynamically from incoming client HTTP request headers (such as Host, X-Forwarded-Host, or Referer).

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 clientDataJSON.type strictly matches 'webauthn.get' for authentication assertions and 'webauthn.create' for registration ceremonies.

Services MUST verify clientDataJSON.type strictly matches 'webauthn.get' for authentication assertions and 'webauthn.create' for registration ceremonies.

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 enforce cryptographic challenge matching in constant time and invalidate session challenges immediately upon receipt, regardless of ceremony success or failure.

Services MUST enforce cryptographic challenge matching in constant time and invalidate session challenges immediately upon receipt, regardless of ceremony success or failure.

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 NEVER execute WebAuthn ceremonies inside embedded frames unless the parent document explicitly grants permission via 'Permissions-Policy

Components NEVER execute WebAuthn ceremonies inside embedded frames unless the parent document explicitly grants permission via 'Permissions-Policy: publickey-credentials-get=(self)'.

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

Frontend authentication handlers MUST verify 'window === window.top' before invoking navigator.credentials.get/create unless explicitly isolated and designated by policy.

Frontend authentication handlers MUST verify 'window === window.top' before invoking navigator.credentials.get/create unless explicitly isolated and designated by policy.

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 Origin Lockout & Top-Level Context Enforcement Standard critical for AI coding assistants?

Enforces cryptographic origin validation and strict Relying Party ID (RP-ID) verification against raw clientDataJSON on the authentication server, coupled with strict Permissions-Policy iframe exclusion. Prevents reverse-proxy Adversary-in-the-Middle (AitM) phishing frameworks from capturing or relaying passkey ceremonies across spoofed or sub-framed origins. 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 (Lenient origin parsing, regex suffix matching, or trusting client headers during WebAuthn assertion verification.) 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