This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: webauthn-ror-cross-subdomain-invariant

FIDO2 WebAuthn Related Origin Requests (ROR) Cross-Subdomain Invariant

Enforces strict origin validation and session isolation during FIDO2 WebAuthn Related Origin Requests (ROR) across federated enterprise subdomains. Prevents compromised or user-controlled subdomains from hijacking passkey assertion ceremonies or poisoning parent domain session states while safely permitting cryptographically verified passkey sharing via authoritative well-known manifests.

Prohibited Anti-Pattern: Wildcard origin matching and broad-domain session issuance during WebAuthn assertion verification

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: FIDO2 WebAuthn Related Origin Requests (ROR) Cross-Subdomain Invariant - Enforces strict origin validation and session isolation during FIDO2 WebAuthn Related Origin Requests (ROR) across federated enterprise subdomains. Prevents compromised or user-controlled subdomains from hijacking passkey assertion ceremonies or poisoning parent domain session states while safely permitting cryptographically verified passkey sharing via authoritative well-known manifests.
globs: src/**/auth/**/*.{ts,tsx,js}, src/**/webauthn/**/*.{ts,tsx,js}, src/**/api/auth/**/*.{ts,tsx,js}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-ror-cross-subdomain-invariant"
---

# FIDO2 WebAuthn Related Origin Requests (ROR) Cross-Subdomain Invariant

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Wildcard origin matching and broad-domain session issuance during WebAuthn assertion verification

## System Constraints
You are a Principal Security Architect enforcing FIDO2 WebAuthn Related Origin Requests (ROR) invariants. You must mandate exact origin-set validation against canonical /.well-known/webauthn manifests, forbid regex-based subdomain parsing, and enforce host-only cookie isolation (__Host- prefix) to prevent cross-subdomain session poisoning.

## Strict Guidelines
- Engineers MUST ALWAYS validate the `clientDataJSON.origin` against an immutable canonical allowlist derived from an authenticated `/.well-known/webauthn` manifest matching the Relying Party ID (rpId).
- Engineers MUST NOT evaluate origins using regex patterns, wildcard matches (e.g., `*.corp.example.com`), or string prefix/suffix checks that allow untrusted sibling subdomains to satisfy assertion checks.
- Services MUST issue host-only session tokens using the `__Host-` cookie prefix without a `Domain` attribute to prevent sibling subdomain token overwrites and session fixation.
- Services MUST verify that `expectedRPID` equals the authoritative effective Top-Level Domain plus one (eTLD+1) defined in the manifest, and reject assertions if `clientDataJSON.type` is not exactly `webauthn.get`.
- Components NEVER accept caller-provided RP IDs from the client request body dynamically; the RP ID must be deterministically bound to the server's tenant configuration.

## Bad vs Good Implementations
### Verifying WebAuthn Authentication Assertion with Related Origin Validation

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Uses a permissive regex for origin validation which permits any subdomain (including unvetted multi-tenant instances) to authenticate credentials. Dynamically trusts caller-supplied RP IDs and issues a wildcard parent-domain cookie (`domain: '.example.com'`), enabling sibling subdomain session poisoning.
```typescript
import { Request, Response } from 'express';
import { verifyAuthenticationResponse } from '@simplewebauthn/server';

export async function verifyAssertion(req: Request, res: Response) {
  const { assertionResponse, tenantSubdomain } = req.body;
  const clientOrigin = req.headers.origin as string;

  // VULNERABILITY: Wildcard regex allows compromised subdomains (e.g., evil-tenant.example.com)
  // or attacker-controlled domains (e.g., example.com.attacker.com) to validate credentials.
  const isAllowedOrigin = /^https:\/\/.*\.example\.com$/.test(clientOrigin);
  if (!isAllowedOrigin) {
    return res.status(403).json({ error: 'Origin not allowed' });
  }

  const verification = await verifyAuthenticationResponse({
    response: assertionResponse,
    expectedChallenge: req.session.challenge,
    expectedOrigin: clientOrigin,
    expectedRPID: tenantSubdomain + '.example.com', // Insecure: dynamically trusted from client
  });

  if (verification.verified) {
    // VULNERABILITY: Setting wildcard cookie allows session poisoning across subdomains
    res.cookie('session_id', 'sess_abc123', {
      domain: '.example.com',
      secure: true,
      httpOnly: true,
      sameSite: 'lax'
    });
    return res.json({ success: true });
  }

  return res.status(400).json({ error: 'Verification failed' });
}
```

#### Production Standard (Correct)
> **Standard**: Enforces strict set-membership validation of the origin against pre-vetted canonical ROR origins, pins the RP ID immutably, requires user verification, and issues an origin-bound, host-only `__Host-` session cookie to categorically eliminate cross-subdomain session poisoning.
```typescript
import { Request, Response } from 'express';
import { verifyAuthenticationResponse } from '@simplewebauthn/server';

// Canonical Related Origin manifest allowlist verified during deployment
const AUTHORITATIVE_RP_ID = 'corp.example.com';
const CANONICAL_RELATED_ORIGINS = new Set([
  'https://auth.corp.example.com',
  'https://portal.corp.example.com',
  'https://finance.corp.example.com'
] as const);

export async function verifyAssertion(req: Request, res: Response) {
  const { assertionResponse } = req.body;
  const rawOrigin = req.headers.origin;

  if (!rawOrigin || typeof rawOrigin !== 'string') {
    return res.status(400).json({ error: 'Missing or malformed Origin header' });
  }

  // INVARIANT 1: Strict canonical membership check against the ROR manifest
  if (!CANONICAL_RELATED_ORIGINS.has(rawOrigin as any)) {
    return res.status(403).json({ error: 'Origin not authorized under ROR policy' });
  }

  const verification = await verifyAuthenticationResponse({
    response: assertionResponse,
    expectedChallenge: req.session.challenge,
    expectedOrigin: rawOrigin,
    expectedRPID: AUTHORITATIVE_RP_ID,
    requireUserVerification: true,
  });

  if (!verification.verified || !verification.authenticationInfo) {
    return res.status(400).json({ error: 'Passkey verification failed' });
  }

  // INVARIANT 2: Issue host-only cookie with __Host- prefix, prohibiting Domain attribute
  res.setHeader('Set-Cookie', [
    `__Host-session=${verification.authenticationInfo.newCounter}; ` +
    'Path=/; Secure; HttpOnly; SameSite=Strict'
  ]);

  return res.json({ success: 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: FIDO2 WebAuthn Related Origin Requests (ROR) Cross-Subdomain Invariant

FIDO2 WebAuthn Related Origin Requests (ROR) Cross-Subdomain Invariant defines an industrial-grade behavioral standard for security engineering. Enforces strict origin validation and session isolation during FIDO2 WebAuthn Related Origin Requests (ROR) across federated enterprise subdomains. Prevents compromised or user-controlled subdomains from hijacking passkey assertion ceremonies or poisoning parent domain session states while safely permitting cryptographically verified passkey sharing via authoritative well-known manifests. 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: Wildcard origin matching and broad-domain session issuance 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 DriftWildcard origin matching and broad-domain session issuance during WebAuthn assertion verificationCritical
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 the `clientDataJSON.origin` against an immutable canonical allowlist derived from an authenticated `/.well-known/webauthn` manifest matching the Relying Party ID (rpId).

Engineers MUST ALWAYS validate the `clientDataJSON.origin` against an immutable canonical allowlist derived from an authenticated `/.well-known/webauthn` manifest matching the Relying Party ID (rpId).

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 evaluate origins using regex patterns, wildcard matches (e.g., `*.corp.example.com`), or string prefix/suffix checks that allow untrusted sibling subdomains to satisfy assertion checks.

Engineers MUST NOT evaluate origins using regex patterns, wildcard matches (e.g., `*.corp.example.com`), or string prefix/suffix checks that allow untrusted sibling subdomains to satisfy assertion checks.

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 issue host-only session tokens using the `__Host-` cookie prefix without a `Domain` attribute to prevent sibling subdomain token overwrites and session fixation.

Services MUST issue host-only session tokens using the `__Host-` cookie prefix without a `Domain` attribute to prevent sibling subdomain token overwrites and session fixation.

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 that `expectedRPID` equals the authoritative effective Top-Level Domain plus one (eTLD+1) defined in the manifest, and reject assertions if `clientDataJSON.type` is not exactly `webauthn.get`.

Services MUST verify that `expectedRPID` equals the authoritative effective Top-Level Domain plus one (eTLD+1) defined in the manifest, and reject assertions if `clientDataJSON.type` is not exactly `webauthn.get`.

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 accept caller-provided RP IDs from the client request body dynamically

Components NEVER accept caller-provided RP IDs from the client request body dynamically; the RP ID must be deterministically bound to the server's tenant configuration.

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 FIDO2 WebAuthn Related Origin Requests (ROR) Cross-Subdomain Invariant critical for AI coding assistants?

Enforces strict origin validation and session isolation during FIDO2 WebAuthn Related Origin Requests (ROR) across federated enterprise subdomains. Prevents compromised or user-controlled subdomains from hijacking passkey assertion ceremonies or poisoning parent domain session states while safely permitting cryptographically verified passkey sharing via authoritative well-known manifests. 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 (Wildcard origin matching and broad-domain session issuance 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

FIDO2