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

WebAuthn L3 PRF Hardware-Bound Symmetric Key Derivation Standards

Enforces deterministic, zero-knowledge client-side encryption key derivation using the W3C WebAuthn Level 3 Pseudo-Random Function (PRF) extension. Mandates HKDF domain separation, strict 32-byte PRF salt validation, explicit hardware PRF support verification, and secure memory zeroization of raw PRF secrets.

Prohibited Anti-Pattern: Using raw WebAuthn PRF extension output directly as a symmetric key without HKDF expansion and missing authenticator PRF support verification

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: WebAuthn L3 PRF Hardware-Bound Symmetric Key Derivation Standards - Enforces deterministic, zero-knowledge client-side encryption key derivation using the W3C WebAuthn Level 3 Pseudo-Random Function (PRF) extension. Mandates HKDF domain separation, strict 32-byte PRF salt validation, explicit hardware PRF support verification, and secure memory zeroization of raw PRF secrets.
globs: src/**/*.{ts,tsx}, lib/**/*.{ts,tsx}, packages/crypto/**/*.{ts,tsx}, services/auth/**/*.{ts,tsx}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-l3-prf-key-derivation-guardrail"
---

# WebAuthn L3 PRF Hardware-Bound Symmetric Key Derivation Standards

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Using raw WebAuthn PRF extension output directly as a symmetric key without HKDF expansion and missing authenticator PRF support verification

## System Constraints
You are a Principal Security Architect enforcing the W3C WebAuthn Level 3 PRF (Pseudo-Random Function) Extension standards for client-side zero-knowledge key derivation. You must enforce hardware capability checks, strict 32-byte PRF input constraints, two-step HKDF domain separation (RFC 5869), and defense against memory exposure of transient PRF buffers.

## Strict Guidelines
- Engineers MUST ALWAYS verify that 'clientExtensionResults.prf?.enabled' or 'clientExtensionResults.prf?.results' is explicitly defined before attempting key extraction.
- Engineers MUST NEVER use raw PRF output buffers directly as encryption keys; PRF output MUST strictly be consumed as an IKM (Input Keying Material) into HKDF (RFC 5869) with a unique application-specific 'info' context string.
- Code MUST strictly validate that PRF evaluation input salts are exactly 32 bytes in length before invoking navigator.credentials.get().
- Services MUST NEVER transmit the derived symmetric key or raw PRF output to the backend; all cryptographic operations (e.g., AES-GCM-256) MUST occur strictly client-side.
- Components NEVER store PRF output buffers in reactive application state, local storage, or long-lived closures, and MUST zeroize raw TypedArrays immediately after HKDF derivation.

## Bad vs Good Implementations
### Hardware PRF Symmetric Key Derivation with HKDF and Zeroization

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: Fails to check if the authenticator actually supported the PRF extension, permits arbitrary salt lengths (must be exactly 32 bytes), uses raw PRF output directly as an AES key without HKDF domain separation (violating cryptographic hygiene), and leaks the raw PRF material indefinitely in memory.
```typescript
// INSECURE: Uses raw PRF buffer directly, assumes PRF succeeded, lacks HKDF domain separation
export async function deriveKeyFromPasskey(credentialId: Uint8Array, salt: Uint8Array): Promise<CryptoKey> {
  const credential = (await navigator.credentials.get({
    publicKey: {
      challenge: crypto.getRandomValues(new Uint8Array(32)),
      allowCredentials: [{ id: credentialId, type: 'public-key' }],
      extensions: {
        prf: {
          eval: {
            first: salt, // Potential length vulnerability (not guaranteed 32 bytes)
          },
        },
      },
    },
  })) as PublicKeyCredential;

  const results = credential.getClientExtensionResults();
  // DANGEROUS: Type assertion bypasses support check, raw buffer used directly as AES key
  const rawSecret = (results as any).prf.results.first as ArrayBuffer;

  return crypto.subtle.importKey(
    'raw',
    rawSecret,
    { name: 'AES-GCM' },
    false,
    ['encrypt', 'decrypt']
  );
}
```

#### Production Standard (Correct)
> **Standard**: Validates the 32-byte salt requirement, verifies `results.prf.results.first` before handling, feeds the secret into HKDF-SHA-256 with an explicit domain separation context string, sets keys as non-extractable, and zeroizes the transient PRF buffer within a `finally` block to mitigate heap exposure.
```typescript
// SECURE: Hardware capability verification, 32-byte salt guarantee, HKDF domain separation, and buffer zeroization
export async function deriveKeyFromPasskey(
  credentialId: Uint8Array,
  salt: Uint8Array,
  domainInfo: string
): Promise<CryptoKey> {
  if (salt.byteLength !== 32) {
    throw new RangeError('WebAuthn PRF salt must be exactly 32 bytes.');
  }

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

  if (!credential) {
    throw new Error('Credential retrieval failed or was canceled.');
  }

  const results = credential.getClientExtensionResults();
  const prfResult = results.prf?.results?.first;

  if (!prfResult || !(prfResult instanceof ArrayBuffer)) {
    throw new Error('Authenticator does not support WebAuthn PRF extension or derivation was denied.');
  }

  const transientPrfBuffer = new Uint8Array(prfResult.slice(0));
  try {
    // 1. Import raw PRF output as raw HKDF Input Keying Material (IKM)
    const prfIkmKey = await crypto.subtle.importKey(
      'raw',
      transientPrfBuffer,
      'HKDF',
      false,
      ['deriveKey']
    );

    // 2. Derive cryptographically domain-separated AES-GCM-256 key via HKDF-SHA-256
    const encoder = new TextEncoder();
    return await crypto.subtle.deriveKey(
      {
        name: 'HKDF',
        hash: 'SHA-256',
        salt: new Uint8Array(32), // Fixed HKDF salt; uniqueness guaranteed by authenticator PRF
        info: encoder.encode(`app:zk-client-encryption:${domainInfo}`),
      },
      prfIkmKey,
      { name: 'AES-GCM', length: 256 },
      false,
      ['encrypt', 'decrypt']
    );
  } finally {
    // 3. Immediately zeroize sensitive memory buffer
    transientPrfBuffer.fill(0);
  }
}
```

Recommended MCP Servers (mcp-serverlist.com)

Equip agent with system tools to verify code for this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: WebAuthn L3 PRF Hardware-Bound Symmetric Key Derivation Standards

WebAuthn L3 PRF Hardware-Bound Symmetric Key Derivation Standards defines an industrial-grade behavioral standard for security engineering. Enforces deterministic, zero-knowledge client-side encryption key derivation using the W3C WebAuthn Level 3 Pseudo-Random Function (PRF) extension. Mandates HKDF domain separation, strict 32-byte PRF salt validation, explicit hardware PRF support verification, and secure memory zeroization of raw PRF secrets. 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: Using raw WebAuthn PRF extension output directly as a symmetric key without HKDF expansion and missing authenticator PRF support 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 DriftUsing raw WebAuthn PRF extension output directly as a symmetric key without HKDF expansion and missing authenticator PRF support 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 verify that 'clientExtensionResults.prf?.enabled' or 'clientExtensionResults.prf?.results' is explicitly defined before attempting key extraction.

Engineers MUST ALWAYS verify that 'clientExtensionResults.prf?.enabled' or 'clientExtensionResults.prf?.results' is explicitly defined before attempting key extraction.

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 PRF output buffers directly as encryption keys

Engineers MUST NEVER use raw PRF output buffers directly as encryption keys; PRF output MUST strictly be consumed as an IKM (Input Keying Material) into HKDF (RFC 5869) with a unique application-specific 'info' context 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

Code MUST strictly validate that PRF evaluation input salts are exactly 32 bytes in length before invoking navigator.credentials.get().

Code MUST strictly validate that PRF evaluation input salts are exactly 32 bytes in length before invoking 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.
4

Services MUST NEVER transmit the derived symmetric key or raw PRF output to the backend

Services MUST NEVER transmit the derived symmetric key or raw PRF output to the backend; all cryptographic operations (e.g., AES-GCM-256) MUST occur strictly client-side.

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 store PRF output buffers in reactive application state, local storage, or long-lived closures, and MUST zeroize raw TypedArrays immediately after HKDF derivation.

Components NEVER store PRF output buffers in reactive application state, local storage, or long-lived closures, and MUST zeroize raw TypedArrays immediately after HKDF 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.
Technical Questions & Answers

Frequently Asked Technical Questions

Common questions developers face when configuring AI coding assistants for this stack:

Q:Why is WebAuthn L3 PRF Hardware-Bound Symmetric Key Derivation Standards critical for AI coding assistants?

Enforces deterministic, zero-knowledge client-side encryption key derivation using the W3C WebAuthn Level 3 Pseudo-Random Function (PRF) extension. Mandates HKDF domain separation, strict 32-byte PRF salt validation, explicit hardware PRF support verification, and secure memory zeroization of raw PRF secrets. 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 (Using raw WebAuthn PRF extension output directly as a symmetric key without HKDF expansion and missing authenticator PRF support 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

WebAuthn