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

WebAuthn Conditional Mediation Session Pinning and Origin Anti-Redressing Protocol

Enforces strict origin bounds verification, framing prevention, and cryptographic challenge-to-session pinning during WebAuthn conditional UI (autofill) credential assertions. Prevents cross-origin passkey credential harvesting, UI redressing/clickjacking, and assertion relay attacks across asynchronous mediation sessions.

Prohibited Anti-Pattern: Unpinned Passkey Autofill Assertions Permitting Frame Redressing and Detached Challenge Consumption

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: WebAuthn Conditional Mediation Session Pinning and Origin Anti-Redressing Protocol - Enforces strict origin bounds verification, framing prevention, and cryptographic challenge-to-session pinning during WebAuthn conditional UI (autofill) credential assertions. Prevents cross-origin passkey credential harvesting, UI redressing/clickjacking, and assertion relay attacks across asynchronous mediation sessions.
globs: src/auth/**/*.{ts,tsx}, src/server/auth/**/*.{ts,js}, src/components/auth/**/*.{tsx,jsx}, src/api/auth/**/*.{ts,js}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-conditional-ui-anti-redressing-guardrail"
---

# WebAuthn Conditional Mediation Session Pinning and Origin Anti-Redressing Protocol

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Unpinned Passkey Autofill Assertions Permitting Frame Redressing and Detached Challenge Consumption

## System Constraints
You are a Principal Security Architect enforcing the WebAuthn Conditional UI Credential Exchange Anti-Redressing Protocol. You must reject any WebAuthn implementation where conditional assertions run in framed contexts, where challenge tokens are not strictly cryptographically pinned to ephemeral user agent sessions, or where the server fails to reject cross-origin assertions and unexpected credential types.

## Strict Guidelines
- Engineers MUST ALWAYS enforce top-level browsing context execution before invoking `navigator.credentials.get({ mediation: 'conditional' })` by validating `window.self === window.top`.
- Engineers MUST ALWAYS generate an ephemeral, single-use, cryptographically secure challenge on the server and bind it directly to an HttpOnly, SameSite=Strict session cookie before dispatching to the client.
- Engineers MUST NEVER permit WebAuthn conditional autofill requests within embedded `<iframe>` elements unless explicitly protected by `Permissions-Policy: publickey-credentials-get=(self)` and isolated trusted origins.
- Server-side verification MUST strictly validate that `clientDataJSON.origin` exactly matches the expected canonical Relying Party origin, including protocol and port, rejecting wildcards or regex partial matches.
- Server-side verification MUST enforce that `clientDataJSON.type` is exactly `'webauthn.get'` and that `clientDataJSON.crossOrigin` is explicitly `false` (or absent/false per W3C specification).
- Services MUST atomically invalidate and consume the authentication challenge immediately upon initial validation attempt to prevent replay or concurrent harvest attempts.
- Components NEVER start conditional mediation without managing an active `AbortController` signal to clean up pending credential requests on component unmount or context switch.

## Bad vs Good Implementations
### Client-Side Safe Conditional Assertion vs Permissive Autofill Execution

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The code fails to verify that it is running in a top-level browsing context (`window.self === window.top`), exposing users to credential harvesting via clickjacking/frame redressing. Furthermore, it lacks an AbortController to cancel dangling assertions on UI unmount and does not bind the assertion attempt to a cryptographic session token.
```typescript
import { startAuthentication } from '@simplewebauthn/browser';

// ANTI-PATTERN: No frame check, unmanaged abort signal, loose challenge consumption
export async function initAutofillAuth() {
  const res = await fetch('/api/auth/challenge');
  const { options } = await res.json();

  // Vulnerable: Permitted to run inside iframes, subject to UI clickjacking/redressing
  const assertion = await startAuthentication({
    optionsJSON: options,
    useBrowserAutofill: true,
  });

  await fetch('/api/auth/verify', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(assertion),
  });
}
```

#### Production Standard (Correct)
> **Standard**: Ensures the invocation occurs exclusively in a top-level browsing context, preventing UI redressing. Binds the interaction to an authenticated `same-origin` session, controls cancellation via `AbortSignal`, and delegates verification to an isolated and strictly validated endpoint.
```typescript
import { startAuthentication } from '@simplewebauthn/browser';
import type { PublicKeyCredentialCreationOptionsJSON } from '@simplewebauthn/types';

export async function initAutofillAuth(signal: AbortSignal): Promise<void> {
  // Invariant 1: Anti-redressing frame enforcement
  if (typeof window !== 'undefined' && window.self !== window.top) {
    throw new Error('SecurityError: WebAuthn Conditional UI execution prohibited in embedded contexts');
  }

  // Invariant 2: Retrieve server challenge pinned to HttpOnly session
  const challengeRes = await fetch('/api/auth/conditional-challenge', {
    method: 'POST',
    credentials: 'same-origin',
    headers: { 'Accept': 'application/json' },
    signal,
  });

  if (!challengeRes.ok) {
    throw new Error('Failed to acquire secure conditional assertion challenge');
  }

  const { optionsJSON } = await challengeRes.json() as { optionsJSON: PublicKeyCredentialCreationOptionsJSON };

  // Invariant 3: Bound conditional authentication with explicit abort signal
  const assertion = await startAuthentication({
    optionsJSON,
    useBrowserAutofill: true,
    verifyBrowserAutofillInput: true,
  });

  const verifyRes = await fetch('/api/auth/conditional-verify', {
    method: 'POST',
    credentials: 'same-origin',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(assertion),
    signal,
  });

  if (!verifyRes.ok) {
    throw new Error('Assertion verification failed');
  }
}
```

### Server-Side Origin and Cryptographic Session Pinning Verification

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Violates architectural invariant, risking production failure or unhandled runtime exceptions.
```typescript
import type { AuthenticationResponseJSON } from '@simplewebauthn/types';

// ANTI-PATTERN: Origin not checked against exact URL, challenge not atomically consumed
export async function verifyAssertionBad(body: AuthenticationResponseJSON, sessionChallenge: string) {
  const clientData = JSON.parse(Buffer.from(body.response.clientDataJSON, 'base64url').toString('utf-8'));

  // Vulnerable: Partial matching allows attacker subdomains or open-redirect harvested origins
  if (!clientData.origin.includes('example.com')) {
    throw new Error('Invalid origin');
  }

  if (clientData.challenge !== sessionChallenge) {
    throw new Error('Challenge mismatch');
  }

  // Vulnerable: Challenge is not invalidated immediately, allowing replay
  return { success: true };
}
```

#### Production Standard (Correct)
> **Standard**: Atomically consumes the single-use challenge prior to verification to eliminate replay and relay attacks. Enforces strict cryptographic parsing via `@simplewebauthn/server`, matching exact canonical origin and RPID strings, and enforcing required user verification.
```typescript
import { verifyAuthenticationResponse } from '@simplewebauthn/server';
import type { AuthenticationResponseJSON } from '@simplewebauthn/types';

interface SessionStore {
  consumeChallenge(sessionId: string): Promise<string | null>;
  getExpectedOrigin(): string;
  getExpectedRPID(): string;
}

export async function verifyAssertionSecure(
  sessionId: string,
  body: AuthenticationResponseJSON,
  sessionStore: SessionStore,
  storedAuthenticator: { credentialID: Uint8Array; credentialPublicKey: Uint8Array; counter: number }
) {
  // Invariant 1: Atomic single-use challenge consumption (anti-replay)
  const expectedChallenge = await sessionStore.consumeChallenge(sessionId);
  if (!expectedChallenge) {
    throw new SecurityError('Challenge missing, expired, or already consumed for this session');
  }

  const expectedOrigin = sessionStore.getExpectedOrigin();
  const expectedRPID = sessionStore.getExpectedRPID();

  // Invariant 2: Strict cryptographic verification with exact origin check
  const verification = await verifyAuthenticationResponse({
    response: body,
    expectedChallenge,
    expectedOrigin,
    expectedRPID,
    authenticator: storedAuthenticator,
    requireUserVerification: true,
  });

  if (!verification.verified || !verification.authenticationInfo) {
    throw new SecurityError('Passkey conditional assertion failed cryptographic verification');
  }

  return verification.authenticationInfo;
}

class SecurityError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'SecurityError';
  }
}
```

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 Mediation Session Pinning and Origin Anti-Redressing Protocol

WebAuthn Conditional Mediation Session Pinning and Origin Anti-Redressing Protocol defines an industrial-grade behavioral standard for security engineering. Enforces strict origin bounds verification, framing prevention, and cryptographic challenge-to-session pinning during WebAuthn conditional UI (autofill) credential assertions. Prevents cross-origin passkey credential harvesting, UI redressing/clickjacking, and assertion relay attacks across asynchronous mediation sessions. 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: Unpinned Passkey Autofill Assertions Permitting Frame Redressing and Detached Challenge Consumption 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 DriftUnpinned Passkey Autofill Assertions Permitting Frame Redressing and Detached Challenge ConsumptionCritical
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 top-level browsing context execution before invoking `navigator.credentials.get({ mediation

Engineers MUST ALWAYS enforce top-level browsing context execution before invoking `navigator.credentials.get({ mediation: 'conditional' })` by validating `window.self === window.top`.

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 generate an ephemeral, single-use, cryptographically secure challenge on the server and bind it directly to an HttpOnly, SameSite=Strict session cookie before dispatching to the client.

Engineers MUST ALWAYS generate an ephemeral, single-use, cryptographically secure challenge on the server and bind it directly to an HttpOnly, SameSite=Strict session cookie before dispatching to the client.

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 NEVER permit WebAuthn conditional autofill requests within embedded `<iframe>` elements unless explicitly protected by `Permissions-Policy

Engineers MUST NEVER permit WebAuthn conditional autofill requests within embedded `<iframe>` elements unless explicitly protected by `Permissions-Policy: publickey-credentials-get=(self)` and isolated trusted origins.

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

Server-side verification MUST strictly validate that `clientDataJSON.origin` exactly matches the expected canonical Relying Party origin, including protocol and port, rejecting wildcards or regex partial matches.

Server-side verification MUST strictly validate that `clientDataJSON.origin` exactly matches the expected canonical Relying Party origin, including protocol and port, rejecting wildcards or regex partial matches.

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

Server-side verification MUST enforce that `clientDataJSON.type` is exactly `'webauthn.get'` and that `clientDataJSON.crossOrigin` is explicitly `false` (or absent/false per W3C specification).

Server-side verification MUST enforce that `clientDataJSON.type` is exactly `'webauthn.get'` and that `clientDataJSON.crossOrigin` is explicitly `false` (or absent/false per W3C specification).

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

Services MUST atomically invalidate and consume the authentication challenge immediately upon initial validation attempt to prevent replay or concurrent harvest attempts.

Services MUST atomically invalidate and consume the authentication challenge immediately upon initial validation attempt to prevent replay or concurrent harvest attempts.

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

Components NEVER start conditional mediation without managing an active `AbortController` signal to clean up pending credential requests on component unmount or context switch.

Components NEVER start conditional mediation without managing an active `AbortController` signal to clean up pending credential requests on component unmount or context switch.

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 Mediation Session Pinning and Origin Anti-Redressing Protocol critical for AI coding assistants?

Enforces strict origin bounds verification, framing prevention, and cryptographic challenge-to-session pinning during WebAuthn conditional UI (autofill) credential assertions. Prevents cross-origin passkey credential harvesting, UI redressing/clickjacking, and assertion relay attacks across asynchronous mediation sessions. 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 (Unpinned Passkey Autofill Assertions Permitting Frame Redressing and Detached Challenge Consumption) 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