This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: webauthn-prf-zero-knowledge-derivation-webauthn-level-3-933

WebAuthn Level 3 PRF Extension Zero-Knowledge Client-Side Key Derivation

Enforces strict zero-knowledge client-side field-level encryption using WebAuthn Level 3 PRF (Pseudo-Random Function) extensions. Raw PRF outputs and derived symmetric encryption keys must remain strictly within volatile client memory and never be transmitted to, cached on, or regenerated by backend services. Cryptographic operations must consume Web Crypto HKDF and AES-GCM primitives with distinct salt-keyed credential lookups.

Prohibited Anti-Pattern: Transmitting PRF Outputs or Derived Decryption Keys to Backend Services

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: WebAuthn Level 3 PRF Extension Zero-Knowledge Client-Side Key Derivation - Enforces strict zero-knowledge client-side field-level encryption using WebAuthn Level 3 PRF (Pseudo-Random Function) extensions. Raw PRF outputs and derived symmetric encryption keys must remain strictly within volatile client memory and never be transmitted to, cached on, or regenerated by backend services. Cryptographic operations must consume Web Crypto HKDF and AES-GCM primitives with distinct salt-keyed credential lookups.
globs: src/**/*.{ts,tsx}, lib/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-prf-zero-knowledge-derivation-webauthn-level-3-933"
---

# WebAuthn Level 3 PRF Extension Zero-Knowledge Client-Side Key Derivation

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Transmitting PRF Outputs or Derived Decryption Keys to Backend Services

## System Constraints
You are a Principal Security Architect enforcing the WebAuthn Level 3 PRF Extension Zero-Knowledge Key Derivation Standard. You must mandate that all client-side decryption and encryption keys derived from hardware authenticator PRF extensions execute completely inside the client sandbox using Web Crypto APIs. You must reject any code transmitting raw PRF outputs, symmetric keys, or non-blinded key material to remote endpoints, and ensure PRF salts are distinct per domain and context.

## Strict Guidelines
- Engineers MUST ALWAYS verify client support for 'prf' in PublicKeyCredential.getClientCapabilities() or authenticator attachment extensions before initiating PRF key derivation.
- Engineers MUST ALWAYS pass credential-specific or context-bound 32-byte salts within the 'prf.eval.first' or 'prf.evalByCredential' dictionary in navigator.credentials.get().
- Engineers MUST ALWAYS derive the final symmetric encryption key using HKDF (RFC 5869) with SHA-256 and an explicit application-bound 'info' parameter from the raw PRF result via window.crypto.subtle.deriveKey.
- Engineers MUST NOT transmit raw PRF output bytes (results.first or results.second) or derived CryptoKey instances to any backend API or external logging service.
- Code MUST mark CryptoKey instances derived from PRF output as non-extractable (extractable: false) to prevent client-side script memory exfiltration.
- Services MUST receive and store only authenticated ciphertext payloads containing nonce/IV, ciphertext, and authentication tags alongside the public WebAuthn credential ID.

## Bad vs Good Implementations
### Hardware PRF Evaluation and Non-Extractable Key Derivation

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The bad example uses an invalid non-32-byte salt, extracts raw PRF output, and transmits the raw hardware-derived secret across the network to a backend API, destroying zero-knowledge properties and exposing the client's master secret to server compromise.
```typescript
export async function decryptUserData(credentialId: string, encryptedPayload: string): Promise<string> {
  // ANTI-PATTERN: Requesting standard authentication and sending PRF outputs or deriving keys insecurely
  const assertion = await navigator.credentials.get({
    publicKey: {
      challenge: new Uint8Array(32),
      allowCredentials: [{ id: Uint8Array.from(atob(credentialId), c => c.charCodeAt(0)), type: 'public-key' }],
      extensions: {
        prf: {
          eval: {
            first: new TextEncoder().encode('global-static-salt') // INSECURE: Non-32-byte and static salt
          }
        }
      }
    }
  }) as PublicKeyCredential;

  const extensionResults = assertion.getClientExtensionResults();
  const rawPrf = new Uint8Array(extensionResults.prf?.results?.first!);

  // CRITICAL VULNERABILITY: Transmitting raw PRF secret to the backend for server-side decryption
  const response = await fetch('/api/decrypt', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      credentialId,
      prfKey: Array.from(rawPrf),
      payload: encryptedPayload
    })
  });

  return response.text();
}
```

#### Production Standard (Correct)
> **Standard**: The good example verifies input constraints (32-byte salt), requests PRF evaluation via WebAuthn Level 3 extensions, imports the raw output solely as non-extractable HKDF key material, derives a non-extractable 256-bit AES-GCM key in volatile browser memory, and never transmits derived key material over the network.
```typescript
export async function deriveClientKeyFromPrf(
  credentialId: Uint8Array,
  salt: Uint8Array,
  info: Uint8Array
): Promise<CryptoKey> {
  if (salt.byteLength !== 32) {
    throw new Error('PRF salt must be exactly 32 bytes.');
  }

  const assertion = await navigator.credentials.get({
    publicKey: {
      challenge: crypto.getRandomValues(new Uint8Array(32)),
      allowCredentials: [{ id: credentialId, type: 'public-key' }],
      extensions: {
        prf: {
          eval: {
            first: salt
          }
        }
      }
    }
  }) as PublicKeyCredential | null;

  if (!assertion) {
    throw new Error('Authentication ceremony aborted.');
  }

  const extensionResults = assertion.getClientExtensionResults();
  const prfOutput = extensionResults.prf?.results?.first;
  if (!prfOutput) {
    throw new Error('Authenticator did not return PRF output.');
  }

  // Import PRF output as raw key material strictly for HKDF derivation
  const prfKeyMaterial = await window.crypto.subtle.importKey(
    'raw',
    prfOutput,
    'HKDF',
    false,
    ['deriveKey']
  );

  // Derive non-extractable AES-GCM key inside Web Crypto boundary
  return window.crypto.subtle.deriveKey(
    {
      name: 'HKDF',
      salt: new Uint8Array(32), // Secondary PRF HKDF salt
      info,
      hash: 'SHA-256'
    },
    prfKeyMaterial,
    { name: 'AES-GCM', length: 256 },
    false, // extractable: MUST be false
    ['encrypt', 'decrypt']
  );
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: WebAuthn Level 3 PRF Extension Zero-Knowledge Client-Side Key Derivation

WebAuthn Level 3 PRF Extension Zero-Knowledge Client-Side Key Derivation defines an industrial-grade behavioral standard for security engineering. Enforces strict zero-knowledge client-side field-level encryption using WebAuthn Level 3 PRF (Pseudo-Random Function) extensions. Raw PRF outputs and derived symmetric encryption keys must remain strictly within volatile client memory and never be transmitted to, cached on, or regenerated by backend services. Cryptographic operations must consume Web Crypto HKDF and AES-GCM primitives with distinct salt-keyed credential lookups. 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: Transmitting PRF Outputs or Derived Decryption Keys to Backend Services 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 DriftTransmitting PRF Outputs or Derived Decryption Keys to Backend ServicesCritical
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 client support for 'prf' in PublicKeyCredential.getClientCapabilities() or authenticator attachment extensions before initiating PRF key derivation.

Engineers MUST ALWAYS verify client support for 'prf' in PublicKeyCredential.getClientCapabilities() or authenticator attachment extensions before initiating PRF key derivation.

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 pass credential-specific or context-bound 32-byte salts within the 'prf.eval.first' or 'prf.evalByCredential' dictionary in navigator.credentials.get().

Engineers MUST ALWAYS pass credential-specific or context-bound 32-byte salts within the 'prf.eval.first' or 'prf.evalByCredential' dictionary in navigator.credentials.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.
3

Engineers MUST ALWAYS derive the final symmetric encryption key using HKDF (RFC 5869) with SHA-256 and an explicit application-bound 'info' parameter from the raw PRF result via window.crypto.subtle.deriveKey.

Engineers MUST ALWAYS derive the final symmetric encryption key using HKDF (RFC 5869) with SHA-256 and an explicit application-bound 'info' parameter from the raw PRF result via window.crypto.subtle.deriveKey.

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

Engineers MUST NOT transmit raw PRF output bytes (results.first or results.second) or derived CryptoKey instances to any backend API or external logging service.

Engineers MUST NOT transmit raw PRF output bytes (results.first or results.second) or derived CryptoKey instances to any backend API or external logging service.

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 mark CryptoKey instances derived from PRF output as non-extractable (extractable

Code MUST mark CryptoKey instances derived from PRF output as non-extractable (extractable: false) to prevent client-side script memory exfiltration.

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 receive and store only authenticated ciphertext payloads containing nonce/IV, ciphertext, and authentication tags alongside the public WebAuthn credential ID.

Services MUST receive and store only authenticated ciphertext payloads containing nonce/IV, ciphertext, and authentication tags alongside the public WebAuthn credential ID.

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 Level 3 PRF Extension Zero-Knowledge Client-Side Key Derivation critical for AI coding assistants?

Enforces strict zero-knowledge client-side field-level encryption using WebAuthn Level 3 PRF (Pseudo-Random Function) extensions. Raw PRF outputs and derived symmetric encryption keys must remain strictly within volatile client memory and never be transmitted to, cached on, or regenerated by backend services. Cryptographic operations must consume Web Crypto HKDF and AES-GCM primitives with distinct salt-keyed credential lookups. 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 (Transmitting PRF Outputs or Derived Decryption Keys to Backend Services) 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