This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: webauthn-l3-rp-id-top-level-assertion-isolation

WebAuthn L3 Cross-Origin RP ID Top-Level Assertion Isolation Policy

Enforces strict top-level browsing context isolation and relying party ID (RP ID) verification in accordance with WebAuthn Level 3 specifications. Mandates explicit Permissions-Policy directives to block unauthorized cross-origin iframe credential assertions and guarantees cryptographically enforced origin binding during server-side verification.

Prohibited Anti-Pattern: Unrestricted Cross-Origin WebAuthn Assertions in Embedded Contexts without Permissions-Policy Isolation

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: WebAuthn L3 Cross-Origin RP ID Top-Level Assertion Isolation Policy - Enforces strict top-level browsing context isolation and relying party ID (RP ID) verification in accordance with WebAuthn Level 3 specifications. Mandates explicit Permissions-Policy directives to block unauthorized cross-origin iframe credential assertions and guarantees cryptographically enforced origin binding during server-side verification.
globs: src/**/auth/**/*.{ts,tsx}, src/**/middleware/**/*.{ts,tsx}, src/**/security/**/*.{ts,tsx}, src/server/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-l3-rp-id-top-level-assertion-isolation"
---

# WebAuthn L3 Cross-Origin RP ID Top-Level Assertion Isolation Policy

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Unrestricted Cross-Origin WebAuthn Assertions in Embedded Contexts without Permissions-Policy Isolation

## System Constraints
You are a Principal Security Architect enforcing the WebAuthn Level 3 Cross-Origin RP ID Top-Level Assertion Isolation Policy. You must strictly forbid implicit cross-origin WebAuthn ceremonies, ensure Permissions-Policy headers explicitly declare publickey-credentials-get rules, and ensure relying-party server verifiers enforce strict origin, topOrigin, and RP ID validation without relying on wildcards or loose regular expressions.

## Strict Guidelines
- Engineers MUST ALWAYS enforce the HTTP response header 'Permissions-Policy: publickey-credentials-get=(self)' or omit cross-origin iframe origins unless explicit federated delegation is required.
- Engineers MUST NOT allow WebAuthn ceremonies inside an iframe without verifying that 'window.self === window.top' or explicitly verifying the WebAuthn L3 'crossOrigin' and 'topOrigin' clientData properties.
- Services MUST validate that the 'rpId' requested matches or is a valid registrable domain suffix of the server-controlled origin and reject arbitrary client-supplied RP IDs.
- Services MUST strictly verify 'clientDataJSON.origin' against the expected fully qualified relying party origin; wildcard matches, protocol mismatches, or fuzzy string comparisons are STRICTLY FORBIDDEN.
- Components NEVER execute 'navigator.credentials.get()' in an embedded frame without checking 'document.featurePolicy?.allowsFeature?.("publickey-credentials-get")' or Permissions-Policy support.

## Bad vs Good Implementations
### Server-side WebAuthn L3 Assertion Verification & Origin/RP ID Binding

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The handler accepts a client-provided RP ID instead of enforcing an authoritative server constant, performs an insecure substring check on clientData.origin which permits attacker origins like 'attacker-example.com', and ignores WebAuthn L3 crossOrigin/topOrigin flags, allowing assertion interception via unauthorized iframes.
```typescript
import type { Request, Response } from 'express';

interface AssertionResponse {
  clientDataJSON: string;
  rpId?: string;
}

export async function verifyAssertion(req: Request, res: Response) {
  const { clientDataJSON, rpId } = req.body as AssertionResponse;
  const clientData = JSON.parse(Buffer.from(clientDataJSON, 'base64').toString('utf8'));

  // VULNERABLE: Accepts untrusted client-provided rpId
  // Allows any subdomain or related origin without top-level context verification
  if (clientData.origin.includes('example.com')) {
    if (clientData.type === 'webauthn.get') {
      return res.status(200).json({ status: 'ok', authenticatedRpId: rpId });
    }
  }

  return res.status(401).json({ error: 'Assertion failed' });
}
```

#### Production Standard (Correct)
> **Standard**: Enforces strict origin equality against an authoritative server-side configuration, inspects WebAuthn L3 'crossOrigin' and 'topOrigin' fields to prevent assertion theft from embedded frames, and prevents RP ID tampering by anchoring the RP ID to the verified server identity.
```typescript
import type { Request, Response } from 'express';

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

interface AssertionPayload {
  clientDataJSON: string;
  rawId: string;
}

const EXPECTED_ORIGIN = 'https://auth.example.com';
const EXPECTED_RP_ID = 'example.com';

export async function verifyAssertion(req: Request, res: Response): Promise<Response> {
  const { clientDataJSON } = req.body as AssertionPayload;
  
  const rawBuffer = Buffer.from(clientDataJSON, 'base64');
  const clientData = JSON.parse(rawBuffer.toString('utf-8')) as WebAuthnL3ClientData;

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

  // WebAuthn L3: Enforce strict origin matching
  if (clientData.origin !== EXPECTED_ORIGIN) {
    return res.status(403).json({ error: 'Origin mismatch detected' });
  }

  // WebAuthn L3: Reject assertions invoked cross-origin without top-level identity match
  if (clientData.crossOrigin === true) {
    if (!clientData.topOrigin || clientData.topOrigin !== EXPECTED_ORIGIN) {
      return res.status(403).json({ error: 'Cross-origin WebAuthn invocation rejected by policy' });
    }
  }

  // RP ID must match the authoritative relying party domain (never trust client parameter)
  const authoritativeRpId = EXPECTED_RP_ID;

  return res.status(200).json({ status: 'verified', rpId: authoritativeRpId });
}
```

### HTTP Security Headers Middleware for WebAuthn Permissions Isolation

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Omits the Permissions-Policy header, allowing untrusted nested iframes to initiate WebAuthn assertion ceremonies on behalf of the user, exposing the authentication session to cross-origin UI redressing and assertion harvesting.
```typescript
import type { Request, Response, NextFunction } from 'express';

export function authHeadersMiddleware(req: Request, res: Response, next: NextFunction) {
  // VULNERABLE: Omits Permissions-Policy for WebAuthn credentials
  // Allows any embedded cross-origin iframe to invoke navigator.credentials.get()
  res.setHeader('X-Frame-Options', 'ALLOWALL');
  next();
}
```

#### Production Standard (Correct)
> **Standard**: Explicitly sets 'Permissions-Policy' to restrict 'publickey-credentials-get' exclusively to '(self)' and disables creation within frames. Employs 'frame-ancestors 'none'' to structurally prevent iframe embedding, ensuring WebAuthn ceremonies occur exclusively in a trusted top-level browsing context.
```typescript
import type { Request, Response, NextFunction } from 'express';

export function authHeadersMiddleware(req: Request, res: Response, next: NextFunction): void {
  // Restrict WebAuthn assertions strictly to the top-level origin
  // Prohibits embedded third-party frames from accessing public key credentials
  res.setHeader(
    'Permissions-Policy',
    'publickey-credentials-get=(self), publickey-credentials-create=()'
  );
  res.setHeader('Content-Security-Policy', "frame-ancestors 'none';");
  res.setHeader('X-Frame-Options', 'DENY');
  next();
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: WebAuthn L3 Cross-Origin RP ID Top-Level Assertion Isolation Policy

WebAuthn L3 Cross-Origin RP ID Top-Level Assertion Isolation Policy defines an industrial-grade behavioral standard for security engineering. Enforces strict top-level browsing context isolation and relying party ID (RP ID) verification in accordance with WebAuthn Level 3 specifications. Mandates explicit Permissions-Policy directives to block unauthorized cross-origin iframe credential assertions and guarantees cryptographically enforced origin binding during server-side verification. 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: Unrestricted Cross-Origin WebAuthn Assertions in Embedded Contexts without Permissions-Policy Isolation 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 DriftUnrestricted Cross-Origin WebAuthn Assertions in Embedded Contexts without Permissions-Policy IsolationCritical
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 the HTTP response header 'Permissions-Policy

Engineers MUST ALWAYS enforce the HTTP response header 'Permissions-Policy: publickey-credentials-get=(self)' or omit cross-origin iframe origins unless explicit federated delegation is 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.
2

Engineers MUST NOT allow WebAuthn ceremonies inside an iframe without verifying that 'window.self === window.top' or explicitly verifying the WebAuthn L3 'crossOrigin' and 'topOrigin' clientData properties.

Engineers MUST NOT allow WebAuthn ceremonies inside an iframe without verifying that 'window.self === window.top' or explicitly verifying the WebAuthn L3 'crossOrigin' and 'topOrigin' clientData properties.

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 validate that the 'rpId' requested matches or is a valid registrable domain suffix of the server-controlled origin and reject arbitrary client-supplied RP IDs.

Services MUST validate that the 'rpId' requested matches or is a valid registrable domain suffix of the server-controlled origin and reject arbitrary client-supplied RP IDs.

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 strictly verify 'clientDataJSON.origin' against the expected fully qualified relying party origin

Services MUST strictly verify 'clientDataJSON.origin' against the expected fully qualified relying party origin; wildcard matches, protocol mismatches, or fuzzy string comparisons are STRICTLY FORBIDDEN.

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 'navigator.credentials.get()' in an embedded frame without checking 'document.featurePolicy?.allowsFeature?.("publickey-credentials-get")' or Permissions-Policy support.

Components NEVER execute 'navigator.credentials.get()' in an embedded frame without checking 'document.featurePolicy?.allowsFeature?.("publickey-credentials-get")' or Permissions-Policy support.

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 Cross-Origin RP ID Top-Level Assertion Isolation Policy critical for AI coding assistants?

Enforces strict top-level browsing context isolation and relying party ID (RP ID) verification in accordance with WebAuthn Level 3 specifications. Mandates explicit Permissions-Policy directives to block unauthorized cross-origin iframe credential assertions and guarantees cryptographically enforced origin binding during server-side verification. 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 (Unrestricted Cross-Origin WebAuthn Assertions in Embedded Contexts without Permissions-Policy Isolation) 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