This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: webauthn-prf-deterministic-key-derivation-invariant

WebAuthn PRF Extension Deterministic Client-Side Key Derivation Invariant

Enforces strict cryptographic isolation and domain-separated HKDF derivation when using WebAuthn Pseudo-Random Function (PRF) extensions for zero-knowledge client-side encryption. Mandates that raw PRF outputs remain client-bound and never leak into transport payloads sent to Relying Party backends.

Prohibited Anti-Pattern: Leaking Raw Authenticator PRF Outputs to Verification Backends or Skipping Cryptographic HKDF Expansion

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: WebAuthn PRF Extension Deterministic Client-Side Key Derivation Invariant - Enforces strict cryptographic isolation and domain-separated HKDF derivation when using WebAuthn Pseudo-Random Function (PRF) extensions for zero-knowledge client-side encryption. Mandates that raw PRF outputs remain client-bound and never leak into transport payloads sent to Relying Party backends.
globs: src/**/*.{ts,tsx}, lib/**/*.{ts,tsx}, packages/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-prf-deterministic-key-derivation-invariant"
---

# WebAuthn PRF Extension Deterministic Client-Side Key Derivation Invariant

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Leaking Raw Authenticator PRF Outputs to Verification Backends or Skipping Cryptographic HKDF Expansion

## System Constraints
You are a Principal Security Architect enforcing deterministic client-side key derivation invariants using WebAuthn PRF (Pseudo-Random Function) extensions. Your mandate is to prevent zero-knowledge cryptographic breaks by ensuring hardware-isolated authenticator secrets never egress client boundaries and are strictly expanded via domain-separated HKDF before use in symmetric ciphers.

## Strict Guidelines
- Engineers MUST ALWAYS strip or isolate PRF extension evaluation results from the WebAuthn AuthenticationCredential before sending assertion payloads to backend Relying Party endpoints.
- Engineers MUST NEVER use raw authenticator PRF outputs directly as symmetric encryption keys; they must be fed into HKDF (RFC 5869) with SHA-256 and an explicit application domain separation string.
- PRF input salts MUST be exactly 32 bytes (256-bit entropy) and deterministically derived or securely retrieved per domain context; never use variable-length or non-cryptographic strings.
- Client code MUST check authenticator PRF capability via `PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()` and verify `getClientExtensionResults().prf?.enabled` or `getClientExtensionResults().prf?.results` presence before proceeding.
- Ephemeral derived keys MUST be stored exclusively in volatile memory (`CryptoKey` instances with `extractable: false`) and NEVER persisted to `localStorage`, `sessionStorage`, `IndexedDB`, or client logs.

## Bad vs Good Implementations
### Zero-Knowledge PRF Key Derivation and Safe Server Attestation

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The code uses a non-32-byte salt, directly forwards the raw PRF evaluation bytes to the backend server (violating zero-knowledge constraints), and omits HKDF expansion, risking cross-protocol key collision.
```typescript
import { startAuthentication } from '@simplewebauthn/browser';

export async function authenticateAndUnlockVault(options: any) {
  // Anti-pattern: Evaluating PRF and transmitting raw extension outputs directly to backend
  const assertion = await startAuthentication({
    ...options,
    extensions: {
      prf: {
        eval: {
          first: new TextEncoder().encode('insecure-short-salt') // Non-32-byte salt
        }
      }
    }
  });

  const prfResults = assertion.getClientExtensionResults().prf;
  const rawPrfKey = prfResults?.results?.first;

  // CRITICAL SECURITY FLAW: Leaking zero-knowledge master secret to server payload
  await fetch('/api/auth/verify', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      assertion,
      rawKeyLeaked: Array.from(new Uint8Array(rawPrfKey as ArrayBuffer))
    })
  });

  // Directly using raw PRF output without HKDF domain separation
  return rawPrfKey;
}
```

#### Production Standard (Correct)
> **Standard**: Validates the 32-byte salt invariant, explicitly removes PRF secrets from the assertion payload sent to the Relying Party backend, and executes HKDF-SHA256 domain expansion into a non-extractable AES-GCM CryptoKey.
```typescript
import { startAuthentication } from '@simplewebauthn/browser';

const PRF_SALT_INFO = new TextEncoder().encode('org.production.app.vault.v1');

export async function authenticateAndUnlockVault(
  options: any,
  deterministicSalt32Bytes: Uint8Array
): Promise<CryptoKey> {
  if (deterministicSalt32Bytes.byteLength !== 32) {
    throw new Error('PRF salt invariant violation: Salt must be exactly 32 bytes');
  }

  const assertion = await startAuthentication({
    ...options,
    extensions: {
      ...options.extensions,
      prf: {
        eval: {
          first: deterministicSalt32Bytes
        }
      }
    }
  });

  const extensions = assertion.getClientExtensionResults();
  const prfResult = extensions.prf?.results?.first;
  if (!prfResult) {
    throw new Error('Authenticator did not evaluate PRF extension');
  }

  // Invariant: Strip PRF outputs or construct a clean assertion payload for RP backend
  const { clientExtensionResults, ...serverSafeAssertion } = assertion;

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

  if (!verificationResponse.ok) {
    throw new Error('Relying Party assertion failed');
  }

  // Expand PRF output using HKDF-SHA256 with domain separation into non-extractable CryptoKey
  const baseKey = await crypto.subtle.importKey(
    'raw',
    prfResult,
    'HKDF',
    false,
    ['deriveKey']
  );

  return await crypto.subtle.deriveKey(
    {
      name: 'HKDF',
      hash: 'SHA-256',
      salt: new Uint8Array(32), // Handled by PRF randomness; static 32-byte zero-salt for HKDF-Extract
      info: PRF_SALT_INFO
    },
    baseKey,
    { name: 'AES-GCM', length: 256 },
    false,
    ['encrypt', 'decrypt']
  );
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: WebAuthn PRF Extension Deterministic Client-Side Key Derivation Invariant

WebAuthn PRF Extension Deterministic Client-Side Key Derivation Invariant defines an industrial-grade behavioral standard for security engineering. Enforces strict cryptographic isolation and domain-separated HKDF derivation when using WebAuthn Pseudo-Random Function (PRF) extensions for zero-knowledge client-side encryption. Mandates that raw PRF outputs remain client-bound and never leak into transport payloads sent to Relying Party backends. 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: Leaking Raw Authenticator PRF Outputs to Verification Backends or Skipping Cryptographic HKDF Expansion 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 DriftLeaking Raw Authenticator PRF Outputs to Verification Backends or Skipping Cryptographic HKDF ExpansionCritical
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 strip or isolate PRF extension evaluation results from the WebAuthn AuthenticationCredential before sending assertion payloads to backend Relying Party endpoints.

Engineers MUST ALWAYS strip or isolate PRF extension evaluation results from the WebAuthn AuthenticationCredential before sending assertion payloads to backend Relying Party endpoints.

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 NEVER use raw authenticator PRF outputs directly as symmetric encryption keys

Engineers MUST NEVER use raw authenticator PRF outputs directly as symmetric encryption keys; they must be fed into HKDF (RFC 5869) with SHA-256 and an explicit application domain separation string.

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

PRF input salts MUST be exactly 32 bytes (256-bit entropy) and deterministically derived or securely retrieved per domain context

PRF input salts MUST be exactly 32 bytes (256-bit entropy) and deterministically derived or securely retrieved per domain context; never use variable-length or non-cryptographic strings.

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

Client code MUST check authenticator PRF capability via `PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()` and verify `getClientExtensionResults().prf?.enabled` or `getClientExtensionResults().prf?.results` presence before proceeding.

Client code MUST check authenticator PRF capability via `PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()` and verify `getClientExtensionResults().prf?.enabled` or `getClientExtensionResults().prf?.results` presence before proceeding.

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

Ephemeral derived keys MUST be stored exclusively in volatile memory (`CryptoKey` instances with `extractable

Ephemeral derived keys MUST be stored exclusively in volatile memory (`CryptoKey` instances with `extractable: false`) and NEVER persisted to `localStorage`, `sessionStorage`, `IndexedDB`, or client logs.

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 PRF Extension Deterministic Client-Side Key Derivation Invariant critical for AI coding assistants?

Enforces strict cryptographic isolation and domain-separated HKDF derivation when using WebAuthn Pseudo-Random Function (PRF) extensions for zero-knowledge client-side encryption. Mandates that raw PRF outputs remain client-bound and never leak into transport payloads sent to Relying Party backends. 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 (Leaking Raw Authenticator PRF Outputs to Verification Backends or Skipping Cryptographic HKDF Expansion) 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