This specification is maintained by the AgentRules Working Group. Have enhancements or want to claim maintainership?Submit Specification →
securitycritical PriorityID: webauthn-largeblob-sync-cryptographic-integrity-envelope

Passkey LargeBlob Synchronized Cryptographic State and Monotonic Integrity Invariant

Enforces client-side cryptographic integrity checks and monotonic sequence versioning on WebAuthn largeBlob storage payloads. Prevents out-of-order writes, stale-state rollbacks, and cross-origin state injection caused by multi-device cloud synchronization ecosystems (e.g., iCloud Keychain, Google Password Manager).

Prohibited Anti-Pattern: Blind writes or raw unversioned AEAD encryption of passkey largeBlob payloads without monotonic sequence binding and RP-credential AAD validation

Export Ready-to-Drop Configuration

Select format below to copy code or download file directly.

---
description: Passkey LargeBlob Synchronized Cryptographic State and Monotonic Integrity Invariant - Enforces client-side cryptographic integrity checks and monotonic sequence versioning on WebAuthn largeBlob storage payloads. Prevents out-of-order writes, stale-state rollbacks, and cross-origin state injection caused by multi-device cloud synchronization ecosystems (e.g., iCloud Keychain, Google Password Manager).
globs: src/**/passkey*.ts, src/**/webauthn*.ts, src/**/auth*.ts, src/**/credentials*.ts
alwaysApply: true
verified_by: "agentrules.org"
license: "CC-BY-4.0"
source: "https://agentrules.org/rules/webauthn-largeblob-sync-cryptographic-integrity-envelope"
---

# Passkey LargeBlob Synchronized Cryptographic State and Monotonic Integrity Invariant

> **Severity**: CRITICAL | **Category**: security
> **Anti-Pattern Warning**: Blind writes or raw unversioned AEAD encryption of passkey largeBlob payloads without monotonic sequence binding and RP-credential AAD validation

## System Constraints
You are a Principal Security Architect enforcing cryptographic integrity, authenticated data binding, and deterministic distributed state invariants on WebAuthn passkey largeBlob payloads. Cloud-synchronized passkeys undergo asynchronous, multi-device replication where concurrent writes or delayed syncing can resurrect stale state, cause split-brain data corruption, or allow replay attacks. You must mandate strict authenticated envelope structures using AEAD (AES-GCM), monotonic sequence counter verification, and Additional Authenticated Data (AAD) bound to the relying party ID and credential ID.

## Strict Guidelines
- Engineers MUST ALWAYS encapsulate largeBlob payloads in an Authenticated Integrity Envelope containing an explicit schema version, monotonic sequence number (or logical vector clock), and UTC millisecond timestamp.
- Engineers MUST ALWAYS bind the Relying Party ID (`rpId`) and binary `credentialId` into the Additional Authenticated Data (AAD) during AEAD encryption (e.g., AES-GCM or ChaCha20-Poly1305) to prevent cross-credential envelope transplantation.
- Engineers MUST NEVER execute a largeBlob write without first reading the existing blob, verifying its authentication tag, and asserting that the incoming payload sequence counter is strictly greater than the persisted counter (`newSequence > currentSequence`).
- Code MUST raise a deterministic `LargeBlobSyncConflictError` when a monotonic sequence regression or concurrent conflict is detected, delegating to an application-level conflict resolution strategy instead of silently overwriting.
- Services MUST NOT store sensitive plaintext secrets in largeBlob without deriving unique, per-credential symmetric keys using HKDF with domain-separated info parameters.

## Bad vs Good Implementations
### Unversioned Blind Passkey LargeBlob Write (Vulnerable to Stale Overwrites & Replay)

#### Bad Antipattern (AI Common Hallucination)
> **Why it fails**: This implementation encrypts raw data directly without binding the Relying Party ID or credential ID as Authenticated Additional Data (AAD), exposing it to cross-credential transplantation. Crucially, it performs a blind write without inspecting the existing largeBlob version, leading to silent state regressions and lost updates when credentials synchronize across multiple devices.
```typescript
export async function saveUserDataToLargeBlob(
  credential: PublicKeyCredential,
  secretData: Uint8Array,
  key: CryptoKey
): Promise<void> {
  // Anti-pattern: Blind encryption without sequence numbers, timestamps, or AAD binding.
  const iv = crypto.getRandomValues(new Uint8Array(12));
  const ciphertext = await crypto.subtle.encrypt(
    { name: 'AES-GCM', iv },
    key,
    secretData
  );

  const payload = new Uint8Array(iv.byteLength + ciphertext.byteLength);
  payload.set(iv, 0);
  payload.set(new Uint8Array(ciphertext), iv.byteLength);

  // Stale or concurrent device sync will silently overwrite newer state
  await navigator.credentials.get({
    publicKey: {
      challenge: crypto.getRandomValues(new Uint8Array(32)),
      allowCredentials: [{ id: credential.rawId, type: 'public-key' }],
      extensions: {
        largeBlob: {
          write: payload
        }
      }
    }
  });
}
```

#### Production Standard (Correct)
> **Standard**: The invariant-compliant implementation performs a read-modify-write operation enforcing a monotonically increasing sequence counter. It binds the relying party ID and credential ID into the AES-GCM Additional Authenticated Data (AAD), preventing cross-credential substitution. If an out-of-order write or multi-device sync collision occurs, a typed `LargeBlobSyncConflictError` is raised.
```typescript
export interface LargeBlobEnvelope {
  version: 1;
  sequence: number;
  timestamp: number;
  payload: Record<string, unknown>;
}

export class LargeBlobSyncConflictError extends Error {
  constructor(public currentSeq: number, public attemptedSeq: number) {
    super(`Sync conflict: remote sequence ${currentSeq} >= attempted sequence ${attemptedSeq}`);
    this.name = 'LargeBlobSyncConflictError';
  }
}

export async function writePasskeyLargeBlobSecure(
  credentialId: Uint8Array,
  rpId: string,
  encryptionKey: CryptoKey,
  updateFn: (prev: LargeBlobEnvelope | null) => { sequence: number; payload: Record<string, unknown> }
): Promise<void> {
  // Step 1: Read existing state and verify integrity envelope
  const readAssertion = await navigator.credentials.get({
    publicKey: {
      challenge: crypto.getRandomValues(new Uint8Array(32)),
      rpId,
      allowCredentials: [{ id: credentialId, type: 'public-key' }],
      extensions: { largeBlob: { read: true } }
    }
  }) as PublicKeyCredential & { getClientExtensionResults: () => { largeBlob?: { blob?: ArrayBuffer } } };

  const currentRawBlob = readAssertion?.getClientExtensionResults()?.largeBlob?.blob;
  const aad = new TextEncoder().encode(`${rpId}:${Array.from(credentialId).join(',')}`);
  let currentEnvelope: LargeBlobEnvelope | null = null;

  if (currentRawBlob && currentRawBlob.byteLength > 28) {
    const iv = new Uint8Array(currentRawBlob.slice(0, 12));
    const ciphertext = currentRawBlob.slice(12);
    const decrypted = await crypto.subtle.decrypt(
      { name: 'AES-GCM', iv, additionalData: aad },
      encryptionKey,
      ciphertext
    );
    currentEnvelope = JSON.parse(new TextDecoder().decode(decrypted)) as LargeBlobEnvelope;
  }

  // Step 2: Generate next payload and enforce monotonic sequence invariance
  const { sequence: nextSequence, payload: nextData } = updateFn(currentEnvelope);
  if (currentEnvelope && nextSequence <= currentEnvelope.sequence) {
    throw new LargeBlobSyncConflictError(currentEnvelope.sequence, nextSequence);
  }

  const newEnvelope: LargeBlobEnvelope = {
    version: 1,
    sequence: nextSequence,
    timestamp: Date.now(),
    payload: nextData
  };

  // Step 3: Encrypt with fresh IV and bound AAD before persisting
  const nextIv = crypto.getRandomValues(new Uint8Array(12));
  const encoded = new TextEncoder().encode(JSON.stringify(newEnvelope));
  const newCiphertext = await crypto.subtle.encrypt(
    { name: 'AES-GCM', iv: nextIv, additionalData: aad },
    encryptionKey,
    encoded
  );

  const writePayload = new Uint8Array(nextIv.byteLength + newCiphertext.byteLength);
  writePayload.set(nextIv, 0);
  writePayload.set(new Uint8Array(newCiphertext), nextIv.byteLength);

  await navigator.credentials.get({
    publicKey: {
      challenge: crypto.getRandomValues(new Uint8Array(32)),
      rpId,
      allowCredentials: [{ id: credentialId, type: 'public-key' }],
      extensions: { largeBlob: { write: writePayload } }
    }
  });
}
```

Recommended Agent Skills (askills.dev)

Ready-to-use executable skill functions tailored to this stack.

Architectural Specification & Invariant Rationale

Architectural Invariant Design: Passkey LargeBlob Synchronized Cryptographic State and Monotonic Integrity Invariant

Passkey LargeBlob Synchronized Cryptographic State and Monotonic Integrity Invariant defines an industrial-grade behavioral standard for security engineering. Enforces client-side cryptographic integrity checks and monotonic sequence versioning on WebAuthn largeBlob storage payloads. Prevents out-of-order writes, stale-state rollbacks, and cross-origin state injection caused by multi-device cloud synchronization ecosystems (e.g., iCloud Keychain, Google Password Manager). 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: Blind writes or raw unversioned AEAD encryption of passkey largeBlob payloads without monotonic sequence binding and RP-credential AAD validation 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 DriftBlind writes or raw unversioned AEAD encryption of passkey largeBlob payloads without monotonic sequence binding and RP-credential AAD validationCritical
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 encapsulate largeBlob payloads in an Authenticated Integrity Envelope containing an explicit schema version, monotonic sequence number (or logical vector clock), and UTC millisecond timestamp.

Engineers MUST ALWAYS encapsulate largeBlob payloads in an Authenticated Integrity Envelope containing an explicit schema version, monotonic sequence number (or logical vector clock), and UTC millisecond timestamp.

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 the Relying Party ID (`rpId`) and binary `credentialId` into the Additional Authenticated Data (AAD) during AEAD encryption (e.g., AES-GCM or ChaCha20-Poly1305) to prevent cross-credential envelope transplantation.

Engineers MUST ALWAYS bind the Relying Party ID (`rpId`) and binary `credentialId` into the Additional Authenticated Data (AAD) during AEAD encryption (e.g., AES-GCM or ChaCha20-Poly1305) to prevent cross-credential envelope transplantation.

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 NEVER execute a largeBlob write without first reading the existing blob, verifying its authentication tag, and asserting that the incoming payload sequence counter is strictly greater than the persisted counter (`newSequence > currentSequence`).

Engineers MUST NEVER execute a largeBlob write without first reading the existing blob, verifying its authentication tag, and asserting that the incoming payload sequence counter is strictly greater than the persisted counter (`newSequence > currentSequence`).

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

Code MUST raise a deterministic `LargeBlobSyncConflictError` when a monotonic sequence regression or concurrent conflict is detected, delegating to an application-level conflict resolution strategy instead of silently overwriting.

Code MUST raise a deterministic `LargeBlobSyncConflictError` when a monotonic sequence regression or concurrent conflict is detected, delegating to an application-level conflict resolution strategy instead of silently overwriting.

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

Services MUST NOT store sensitive plaintext secrets in largeBlob without deriving unique, per-credential symmetric keys using HKDF with domain-separated info parameters.

Services MUST NOT store sensitive plaintext secrets in largeBlob without deriving unique, per-credential symmetric keys using HKDF with domain-separated info parameters.

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 Passkey LargeBlob Synchronized Cryptographic State and Monotonic Integrity Invariant critical for AI coding assistants?

Enforces client-side cryptographic integrity checks and monotonic sequence versioning on WebAuthn largeBlob storage payloads. Prevents out-of-order writes, stale-state rollbacks, and cross-origin state injection caused by multi-device cloud synchronization ecosystems (e.g., iCloud Keychain, Google Password Manager). 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 (Blind writes or raw unversioned AEAD encryption of passkey largeBlob payloads without monotonic sequence binding and RP-credential AAD validation) 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

Passkey