This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: webauthn-prf-wasm-memory-quarantine

WebAuthn PRF Key Quarantine and Isolated WASM Zeroization

Mandates that raw outputs from the WebAuthn PRF (Pseudo-Random Function) extension and resulting derived symmetric keys are quarantined exclusively inside isolated WebAssembly linear memory heaps. Enforces immediate deterministic zeroization post-cryptographic operations to eliminate persistent key exposure across the garbage-collected JavaScript runtime heap.

Prohibited Anti-Pattern: Exposing Raw WebAuthn PRF Secrets to Garbage-Collected JavaScript Heaps or Browser Storage

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: WebAuthn PRF Key Quarantine and Isolated WASM Zeroization - Mandates that raw outputs from the WebAuthn PRF (Pseudo-Random Function) extension and resulting derived symmetric keys are quarantined exclusively inside isolated WebAssembly linear memory heaps. Enforces immediate deterministic zeroization post-cryptographic operations to eliminate persistent key exposure across the garbage-collected JavaScript runtime heap.
globs: src/**/*.{ts,tsx,js,mjs}
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-prf-wasm-memory-quarantine"
---

# WebAuthn PRF Key Quarantine and Isolated WASM Zeroization

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Exposing Raw WebAuthn PRF Secrets to Garbage-Collected JavaScript Heaps or Browser Storage

## System Constraints
You are a Principal Security Architect enforcing zero-trust cryptographic key management for WebAuthn PRF extension workflows. The JavaScript engine garbage collector (V8/SpiderMonkey) does not guarantee memory zeroization, leaving cryptographic material vulnerable to heap-dumping, Spectre-style side channels, and DOM cross-site script inspection. You MUST enforce that all PRF-derived material passes directly into an isolated WebAssembly linear memory heap, executes decryption/encryption inside the sandbox, and deterministically scrubs the allocated memory pages immediately upon completion.

## Strict Guidelines
- Engineers MUST ALWAYS transfer WebAuthn PRF extension results directly into a designated WebAssembly linear memory boundary and scrub the intermediary JS buffer with `crypto.getRandomValues()` immediately.
- Engineers MUST NOT persist WebAuthn PRF raw outputs or derived keys in `localStorage`, `sessionStorage`, `IndexedDB`, React/Vue state, or long-lived closures.
- Cryptographic operations utilizing PRF-derived keys (HKDF, AES-256-GCM, ChaCha20-Poly1305) MUST execute within the isolated WebAssembly module rather than exposing extractable CryptoKey instances in the global scope.
- Services MUST wrap client-side decryption routines in `try...finally` blocks that invoke explicit memory scrubbing routines (`memset` / WASM zeroization export) even if an unhandled decryption error occurs.
- Components NEVER represent PRF-derived secrets as standard JavaScript strings, base64 strings, or unmanaged ArrayBuffers.

## Bad vs Good Implementations
### WebAuthn PRF Extraction and Decryption

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: The raw PRF key is instantiated as a standard JavaScript Uint8Array, stored in sessionStorage, and imported via Web Crypto without zeroization. Because V8 controls object lifetimes via non-deterministic garbage collection, the raw secret remains in process memory indefinitely and can be harvested via XSS or prototype pollution.
```typescript
export async function unlockUserVault(assertion: PublicKeyCredential): Promise<Uint8Array> {
  // VULNERABLE: PRF result is stored in standard JS GC memory and exposed to DOM heap inspection
  const extensionResults = assertion.getClientExtensionResults();
  const prfResult = extensionResults.prf?.results?.first;
  if (!prfResult) throw new Error('PRF output unavailable');

  // Storing raw key in JS heap makes it non-zeroizable and subject to memory leakage
  const rawKey = new Uint8Array(prfResult);
  window.sessionStorage.setItem('cached_prf_key', btoa(String.fromCharCode(...rawKey)));

  const cryptoKey = await crypto.subtle.importKey(
    'raw',
    rawKey,
    { name: 'AES-GCM' },
    false,
    ['decrypt']
  );

  const ciphertext = await fetchVaultCiphertext();
  const iv = ciphertext.slice(0, 12);
  const data = ciphertext.slice(12);

  const decrypted = await crypto.subtle.decrypt(
    { name: 'AES-GCM', iv },
    cryptoKey,
    data
  );

  return new Uint8Array(decrypted);
}
```

#### Production Standard (Correct)
> **Standard**: The raw PRF output is quickly copied into an isolated WebAssembly linear memory space, and the JavaScript view is overwritten with pseudorandom values using `crypto.getRandomValues()`. Decryption takes place within the WASM sandbox, and the key space is wiped inside a `finally` block to ensure deterministic destruction regardless of runtime execution failures.
```typescript
import { WasmCryptoSandbox } from './crypto-wasm-module';

export async function unlockUserVault(assertion: PublicKeyCredential): Promise<Uint8Array> {
  const extensionResults = assertion.getClientExtensionResults();
  const prfResult = extensionResults.prf?.results?.first;
  if (!prfResult) throw new Error('PRF output unavailable');

  // Transient buffer created strictly for immediate zero-copy handoff
  const ephemeralPrfBuffer = new Uint8Array(prfResult);
  const wasmSandbox = await WasmCryptoSandbox.getInstance();
  
  let decryptedPayload: Uint8Array;
  const keyPointer = wasmSandbox.allocate(ephemeralPrfBuffer.byteLength);

  try {
    // 1. Copy key material into the isolated WebAssembly linear memory heap
    wasmSandbox.copyToMemory(ephemeralPrfBuffer, keyPointer);
    
    // 2. Deterministically scrub the JS ArrayBuffer immediately
    crypto.getRandomValues(ephemeralPrfBuffer);
    
    const ciphertext = await fetchVaultCiphertext();
    
    // 3. Perform symmetric decryption entirely within the WASM sandbox
    decryptedPayload = wasmSandbox.decryptAesGcm(
      keyPointer,
      ephemeralPrfBuffer.byteLength,
      ciphertext
    );
  } finally {
    // 4. Invariant: Guarantee zeroization of isolated WASM memory pages
    wasmSandbox.zeroizeMemory(keyPointer, ephemeralPrfBuffer.byteLength);
    wasmSandbox.deallocate(keyPointer);
  }

  return decryptedPayload;
}
```

Architectural Specification & Invariant Rationale

Architectural Invariant Design: WebAuthn PRF Key Quarantine and Isolated WASM Zeroization

WebAuthn PRF Key Quarantine and Isolated WASM Zeroization defines an industrial-grade behavioral standard for security engineering. Mandates that raw outputs from the WebAuthn PRF (Pseudo-Random Function) extension and resulting derived symmetric keys are quarantined exclusively inside isolated WebAssembly linear memory heaps. Enforces immediate deterministic zeroization post-cryptographic operations to eliminate persistent key exposure across the garbage-collected JavaScript runtime heap. 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: Exposing Raw WebAuthn PRF Secrets to Garbage-Collected JavaScript Heaps or Browser Storage 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 DriftExposing Raw WebAuthn PRF Secrets to Garbage-Collected JavaScript Heaps or Browser StorageCritical
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 transfer WebAuthn PRF extension results directly into a designated WebAssembly linear memory boundary and scrub the intermediary JS buffer with `crypto.getRandomValues()` immediately.

Engineers MUST ALWAYS transfer WebAuthn PRF extension results directly into a designated WebAssembly linear memory boundary and scrub the intermediary JS buffer with `crypto.getRandomValues()` immediately.

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 persist WebAuthn PRF raw outputs or derived keys in `localStorage`, `sessionStorage`, `IndexedDB`, React/Vue state, or long-lived closures.

Engineers MUST NOT persist WebAuthn PRF raw outputs or derived keys in `localStorage`, `sessionStorage`, `IndexedDB`, React/Vue state, or long-lived closures.

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

Cryptographic operations utilizing PRF-derived keys (HKDF, AES-256-GCM, ChaCha20-Poly1305) MUST execute within the isolated WebAssembly module rather than exposing extractable CryptoKey instances in the global scope.

Cryptographic operations utilizing PRF-derived keys (HKDF, AES-256-GCM, ChaCha20-Poly1305) MUST execute within the isolated WebAssembly module rather than exposing extractable CryptoKey instances in the global scope.

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 wrap client-side decryption routines in `try...finally` blocks that invoke explicit memory scrubbing routines (`memset` / WASM zeroization export) even if an unhandled decryption error occurs.

Services MUST wrap client-side decryption routines in `try...finally` blocks that invoke explicit memory scrubbing routines (`memset` / WASM zeroization export) even if an unhandled decryption error occurs.

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 represent PRF-derived secrets as standard JavaScript strings, base64 strings, or unmanaged ArrayBuffers.

Components NEVER represent PRF-derived secrets as standard JavaScript strings, base64 strings, or unmanaged ArrayBuffers.

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 Key Quarantine and Isolated WASM Zeroization critical for AI coding assistants?

Mandates that raw outputs from the WebAuthn PRF (Pseudo-Random Function) extension and resulting derived symmetric keys are quarantined exclusively inside isolated WebAssembly linear memory heaps. Enforces immediate deterministic zeroization post-cryptographic operations to eliminate persistent key exposure across the garbage-collected JavaScript runtime heap. 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 (Exposing Raw WebAuthn PRF Secrets to Garbage-Collected JavaScript Heaps or Browser Storage) 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