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

WebAuthn Conditional UI Hybrid Passkey Autofill Injection Mitigation

Enforces cryptographic and DOM-isolation invariants for WebAuthn Conditional Mediation (passkey autofill). Prevents malicious iframes, prototype pollution, and rogue extension DOM injections from intercepting hybrid transport credentials during asynchronous form hydration by enforcing AbortController teardowns, immutable challenge-binding, top-level ancestor validation, and strict input attribute isolation.

Prohibited Anti-Pattern: Unisolated Conditional Passkey Requests Vulnerable to Malicious Iframe Hijacking and DOM Injection

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: WebAuthn Conditional UI Hybrid Passkey Autofill Injection Mitigation - Enforces cryptographic and DOM-isolation invariants for WebAuthn Conditional Mediation (passkey autofill). Prevents malicious iframes, prototype pollution, and rogue extension DOM injections from intercepting hybrid transport credentials during asynchronous form hydration by enforcing AbortController teardowns, immutable challenge-binding, top-level ancestor validation, and strict input attribute isolation.
globs: src/**/*.{ts,tsx,js,jsx}, pages/**/*.{ts,tsx}, app/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-conditional-ui-autofill-injection-mitigation"
---

# WebAuthn Conditional UI Hybrid Passkey Autofill Injection Mitigation

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Unisolated Conditional Passkey Requests Vulnerable to Malicious Iframe Hijacking and DOM Injection

## System Constraints
You are a Principal Security Architect enforcing zero-trust standards on WebAuthn Conditional Mediation ceremonies. You mandate strict top-level execution boundaries, iframe ancestry verification, cryptographic state separation, dynamic AbortController teardown on DOM unmount or manual trigger invocation, and defensive sanitization of injected autofill input nodes to prevent passkey exfiltration and session fixation.

## Strict Guidelines
- Engineers MUST ALWAYS verify window.self === window.top and ensure strict Permissions-Policy: publickey-credentials-get=(self) before invoking navigator.credentials.get with mediation: 'conditional'.
- Engineers MUST ALWAYS bind an exclusive AbortController to conditional passkey hydration and abort immediately before initiating modal ceremonies or when unmounting the host DOM input.
- Engineers MUST NOT rely on mutable form inputs to supply challenge buffers, relyingParty identifiers, or allowCredentials lists; these options MUST be fetched over TLS via cryptographically signed sessions and stored in unexposed lexical scopes.
- Components NEVER attach autocomplete='webauthn' to dynamic, unvalidated, or innerHTML-generated inputs, and MUST explicitly enforce type='text' or type='username' with strict CSP nonce verification.
- Code MUST deeply freeze credential request options and strictly validate the returned AuthenticatorAssertionResponse clientDataJSON against expected origins and top-level ancestor contexts prior to server dispatch.

## Bad vs Good Implementations
### Vulnerable vs. Secure Conditional UI Passkey Hydration Lifecycle

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Executes within arbitrary frames without checking window.top, reads the cryptographic challenge from a mutable DOM attribute vulnerable to XSS/DOM-injection, lacks an AbortController causing conflicting WebAuthn requests, and lacks server-session cryptographic binding.
```typescript
import React, { useEffect } from 'react';

export const LoginForm: React.FC = () => {
  useEffect(() => {
    // VULNERABLE: No frame isolation check, vulnerable to iframe hijacking
    // VULNERABLE: No AbortController management, race condition on re-render
    // VULNERABLE: Pulls challenge from mutable DOM dataset
    const challengeStr = document.getElementById('login-form')?.getAttribute('data-challenge');
    if (!challengeStr) return;

    navigator.credentials.get({
      mediation: 'conditional',
      publicKey: {
        challenge: Uint8Array.from(atob(challengeStr), c => c.charCodeAt(0)),
        rpId: window.location.hostname,
        userVerification: 'preferred'
      }
    }).then(async (cred) => {
      // VULNERABLE: Direct post without origin / state verification
      await fetch('/api/webauthn/verify', { method: 'POST', body: JSON.stringify(cred) });
    });
  }, []);

  return (
    <form id="login-form" data-challenge="s3cr3tChallenge">
      <input type="text" name="username" autoComplete="username webauthn" />
      <button type="submit">Sign In</button>
    </form>
  );
};
```

#### Production Standard (Correct)
> **Standard**: Enforces top-level execution boundaries (window.self === window.top), maintains lifecycle-aware AbortController cleanup to prevent pending conditional requests when forms unmount or submit, pulls immutable options directly from a trusted API callback rather than the DOM, and validates the clientDataJSON origin before network transmission.
```typescript
import React, { useEffect, useRef } from 'react';

interface PasskeyOptions {
  challenge: string;
  rpId: string;
  timeout?: number;
}

export const SecureLoginForm: React.FC<{ fetchOptions: () => Promise<PasskeyOptions> }> = ({ fetchOptions }) => {
  const abortControllerRef = useRef<AbortController | null>(null);
  const inputRef = useRef<HTMLInputElement | null>(null);

  useEffect(() => {
    // GUARDRAIL: Strict top-level context assertion
    if (window.self !== window.top) {
      console.error('Security invariant violated: Conditional WebAuthn prohibited in framed contexts');
      return;
    }

    let isMounted = true;
    const controller = new AbortController();
    abortControllerRef.current = controller;

    async function initConditionalUI() {
      if (!window.PublicKeyCredential || !PublicKeyCredential.isConditionalMediationAvailable) {
        return;
      }
      const available = await PublicKeyCredential.isConditionalMediationAvailable();
      if (!available || !isMounted) return;

      const options = Object.freeze(await fetchOptions());
      const rawChallenge = Uint8Array.from(atob(options.challenge), c => c.charCodeAt(0));

      try {
        const credential = await navigator.credentials.get({
          mediation: 'conditional',
          signal: controller.signal,
          publicKey: {
            challenge: rawChallenge,
            rpId: options.rpId,
            userVerification: 'preferred'
          }
        }) as PublicKeyCredential | null;

        if (!isMounted || !credential) return;

        const response = credential.response as AuthenticatorAssertionResponse;
        const clientData = JSON.parse(new TextDecoder().decode(response.clientDataJSON));
        
        // GUARDRAIL: Client-side origin pinning prior to transit
        if (clientData.origin !== window.location.origin) {
          throw new Error('Mismatched origin detected in assertion clientDataJSON');
        }

        await fetch('/api/webauthn/verify', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
          body: JSON.stringify({
            id: credential.id,
            rawId: btoa(String.fromCharCode(...new Uint8Array(credential.rawId))),
            response: {
              clientDataJSON: btoa(String.fromCharCode(...new Uint8Array(response.clientDataJSON))),
              authenticatorData: btoa(String.fromCharCode(...new Uint8Array(response.authenticatorData))),
              signature: btoa(String.fromCharCode(...new Uint8Array(response.signature))),
              userHandle: response.userHandle ? btoa(String.fromCharCode(...new Uint8Array(response.userHandle))) : null
            },
            type: credential.type
          })
        });
      } catch (err: unknown) {
        if ((err as Error)?.name !== 'AbortError') {
          console.error('Conditional WebAuthn failed', err);
        }
      }
    }

    initConditionalUI();

    return () => {
      isMounted = false;
      controller.abort();
      abortControllerRef.current = null;
    };
  }, [fetchOptions]);

  return (
    <form onSubmit={(e) => e.preventDefault()}>
      <input
        ref={inputRef}
        type="text"
        name="username"
        id="auth-username"
        autoComplete="username webauthn"
        required
      />
      <button type="submit">Sign In</button>
    </form>
  );
};
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: WebAuthn Conditional UI Hybrid Passkey Autofill Injection Mitigation

WebAuthn Conditional UI Hybrid Passkey Autofill Injection Mitigation defines an industrial-grade behavioral standard for security engineering. Enforces cryptographic and DOM-isolation invariants for WebAuthn Conditional Mediation (passkey autofill). Prevents malicious iframes, prototype pollution, and rogue extension DOM injections from intercepting hybrid transport credentials during asynchronous form hydration by enforcing AbortController teardowns, immutable challenge-binding, top-level ancestor validation, and strict input attribute isolation. 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: Unisolated Conditional Passkey Requests Vulnerable to Malicious Iframe Hijacking and DOM Injection 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 DriftUnisolated Conditional Passkey Requests Vulnerable to Malicious Iframe Hijacking and DOM InjectionCritical
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 window.self === window.top and ensure strict Permissions-Policy

Engineers MUST ALWAYS verify window.self === window.top and ensure strict Permissions-Policy: publickey-credentials-get=(self) before invoking navigator.credentials.get with mediation: 'conditional'.

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 bind an exclusive AbortController to conditional passkey hydration and abort immediately before initiating modal ceremonies or when unmounting the host DOM input.

Engineers MUST ALWAYS bind an exclusive AbortController to conditional passkey hydration and abort immediately before initiating modal ceremonies or when unmounting the host DOM input.

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 NOT rely on mutable form inputs to supply challenge buffers, relyingParty identifiers, or allowCredentials lists

Engineers MUST NOT rely on mutable form inputs to supply challenge buffers, relyingParty identifiers, or allowCredentials lists; these options MUST be fetched over TLS via cryptographically signed sessions and stored in unexposed lexical scopes.

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

Components NEVER attach autocomplete='webauthn' to dynamic, unvalidated, or innerHTML-generated inputs, and MUST explicitly enforce type='text' or type='username' with strict CSP nonce verification.

Components NEVER attach autocomplete='webauthn' to dynamic, unvalidated, or innerHTML-generated inputs, and MUST explicitly enforce type='text' or type='username' with strict CSP nonce verification.

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

Code MUST deeply freeze credential request options and strictly validate the returned AuthenticatorAssertionResponse clientDataJSON against expected origins and top-level ancestor contexts prior to server dispatch.

Code MUST deeply freeze credential request options and strictly validate the returned AuthenticatorAssertionResponse clientDataJSON against expected origins and top-level ancestor contexts prior to server dispatch.

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 Hybrid Passkey Autofill Injection Mitigation critical for AI coding assistants?

Enforces cryptographic and DOM-isolation invariants for WebAuthn Conditional Mediation (passkey autofill). Prevents malicious iframes, prototype pollution, and rogue extension DOM injections from intercepting hybrid transport credentials during asynchronous form hydration by enforcing AbortController teardowns, immutable challenge-binding, top-level ancestor validation, and strict input attribute isolation. 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 (Unisolated Conditional Passkey Requests Vulnerable to Malicious Iframe Hijacking and DOM Injection) 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