Internal review

External audit handoff

Entry point for an external auditor: scope, what to verify independently versus trust as a baseline, and what is in flight.

External audit handoff

This document is the entry point for an external security audit engagement against @shieldfive/crypto, the open-source cryptography library. It is written for an auditor or audit firm walking into the codebase cold and trying to figure out where to start.

The published crypto-library review produced six task documents and a triage table of their findings. The framing this document gives is: what was looked at, how deep, what to re-verify, what to trust as a starting baseline, and what is in flight at handoff.

Scope of the internal review

What was reviewed

@shieldfive/crypto library (separate GitHub repository shieldfive/crypto):

  • v0 and v1 wire formats — spec/format-v0.md, spec/format-v1.md, and the corresponding parsers (src/format/, src/suites/*-v1/).
  • Key derivation tree — spec/key-derivation.md. Argon2id presets, HKDF-SHA-256 info-string domain separation, ML-KEM-1024 keypair derivation from a 64-byte master secret split into (d, z), master-secret-to-recovery-key derivation.
  • Threat model — spec/threat-model.md. For each protected-against threat, the mechanism. For each excluded threat, verification it remains excluded under v1.
  • AEAD usage discipline — nonce reuse prevention, AAD non-emptiness, tag-check-before-plaintext, wrong-key fail-fast across v0 and v1 suites.

Client-side crypto integration (ShieldFive web repository):

  • Streaming worker invariants in utils/sfCryptoWorkerImpl.ts — single-frame-in-flight under every path (encrypt/decrypt × v0/v1 × happy/error). Content key zeroing on completion and on abort.
  • Upload proof system — utils/uploadProof.ts, utils/uploadProofClient.ts. v0/v1 proof shapes, three-way cross-check (client/server/B2), proof-key uniqueness, timing-safe MAC comparison, version confusion.

What was not reviewed

These surfaces are outside the published crypto-library review and are expected to be in scope for an external engagement, or are explicitly deferred to a follow-up engagement:

  • Cipher suite 0x04 (aes-gcm-v2) — the review covered the three suites in force at the time (0x01 AES-256-GCM, 0x02 XChaCha20-Poly1305, 0x03 ML-KEM-1024 hybrid); suite 0x04 was added to @shieldfive/crypto in 1.0.0-alpha.11 after this review completed and is not covered here. It is opt-in via a dedicated subpath import only — the production default remains Suite 0x03 — and it is queued for the same audit-firm-depth review the other suites received.
  • Server-side and web-application surfaces — share-password and share-link handling, the service-role boundary, RLS policies, database constraints and triggers, RPC function authorization, and the consolidated web-application surfaces were reviewed separately and are kept in the private web repository; they are not part of this published handoff.
  • Mobile application — the mobile/ repo is in active development but has not been brought under the internal review. Per the plan, mobile follows the web application stabilization.
  • Infrastructure layer — Vercel deployment configuration, edge-network behavior, Vercel build environment, secrets storage at the platform layer.
  • B2 bucket policy — Backblaze B2 bucket configuration, cross-account replication boundaries, direct-upload URL scope.
  • Backup and disaster recovery proceduredocs/ops/backups.md, docs/ops/disaster-recovery.md exist; their security properties under restore have not been validated.
  • CSP / XSS under live computationdocs/security/csp-checklist.md is a checklist of policies enforced at the response layer. Live XSS surface coverage is external work.
  • Third-party services beyond their public APIs — Stripe, Supabase, Backblaze B2, Resend. The integration surfaces are reviewed; the services themselves are trust-the-vendor.

Method

Each task document follows a fixed template:

  • Summary — one paragraph: did the area hold up, highest-impact finding.
  • Findings — one entry per drift, numbered N.M. Each entry carries Severity, Affects, Component, Description (with file:line citations), Reproduction or evidence, Recommendation.
  • What I checked but did not find issues with — mandatory. This is the audit trail that distinguishes a review from a checklist; without it, a future reader cannot tell whether an unmentioned area was covered-and-clean or simply skipped.
  • Out of scope (deferred to other tasks) — explicit handoffs to other task documents or to external audit.
  • References — file paths and (where available) commit SHAs pinning the state reviewed.

Findings are numbered TASK.M (e.g. 2.3 is the third finding in Task 2) and tracked in triage.md as one row per finding.

Severity legend

Used consistently across every task in this review:

  • Critical — an attacker can recover plaintext, recover keys, or impersonate a user. Production fix required before any other work.
  • High — an attacker can deny service to a user, exfiltrate metadata they shouldn't see, or bypass an access control that's not crypto-level. Fix required within days.
  • Medium — a defense-in-depth layer is weaker than documented, or spec drift that could lead to a future bug. Fix on next planned work in the area.
  • Low — documentation drift, dead code, hardening opportunity. Fix when convenient.
  • Informational — observation without an action item. The "what I checked" sections are implicit informational findings.

Known limits

The depth is uneven by design.

  • Tasks 1–6 were reviewed at audit-firm depth. Each task is a focused 2–4 hour session on one surface, with full enumeration of the surface, file-and-line citations for every finding, and an explicit "what I checked and did not find issues with" section. The reading audience for these documents is an auditor who wants to skim what was looked at and where the attention concentrated.
  • The review is static-inspection-heavy. The wire-format parsers, key-derivation tree, and AEAD discipline were inspected at the code level rather than exercised under live adversarial pressure or fuzzing. An external engagement is expected to do the live-probe and differential-testing work.
  • The review covers library state at the time it was written. The per-document references section pins the commit SHA reviewed; the library moves, so re-pin before relying on a citation.

What to verify vs trust

For an external engagement under time pressure, these are suggested allocations:

Verify independently — load-bearing invariants

  • Crypto invariants in @shieldfive/crypto:
    • MAC-verify ordering before suite-payload parse (1.4a, 1.4b in task-01).
    • Cross-field header invariant in validateHeaderInputs (1.5).
    • HKDF info-string domain separation; no info-string reuse across contexts (2.5, 2.6 in task-02).
    • ML-KEM-1024 keypair derivation and the (d, z) seed split (Task 2).
  • Streaming worker invariants — single-frame-in-flight and content-key zeroing in task-05.
  • Upload proof cross-check — the three-way client/server/B2 proof verification in task-06.

Trust as a starting baseline — start from, don't redo

  • Scope enumeration. The list of files, routes, RPCs, and tables in each task document is the result of a deliberate enumeration pass. Re-enumerating before starting work would duplicate effort; the right move is to read the enumeration and flag anything that looks missing.
  • Finding catalogue structure. triage.md is the state-of-everything table. An external engagement can append to it under the existing severity/status convention rather than building a parallel catalogue.
  • "What was checked and clean" sections. Each task document's "what I checked but did not find issues with" section is the internal review's positive claim about each surface. Treat those as the internal review's positive findings — they are claims that an external engagement can re-verify but should not need to re-derive from scratch.

Re-verify with fresh eyes — if calendar allows

  • Differential and fuzz testing of the parsers — the v0/v1 decode paths and the suite dispatch were reviewed by inspection; an external engagement is the right place to drive them under malformed-input fuzzing and cross-implementation differential testing.
  • ML-KEM-1024 derivation against the reference — the deterministic (d, z) seed split and keypair derivation were checked against the spec by reading; re-deriving against a reference implementation is worth the fresh eyes.

Suggested first 1–2 days

A pragmatic time allocation for an auditor under time pressure:

  1. Read this HANDOFF (~2 hrs). End with a written list of questions or surfaces you want more on. The internal review does not pretend to be exhaustive; the list of questions is the honest input to the engagement scope.
  2. Read Tasks 1, 2, 3 (~3 hrs) — wire format, key derivation, threat model. These are the crypto core, written at audit-firm depth, and the foundation everything else sits on.
  3. Read Tasks 4, 5, 6 (~2 hrs) — AEAD usage discipline, streaming worker invariants, upload proof system. The client-side integration the wire format relies on.
  4. Walk the triage table (~1 hr). Spot the rows marked Open and read the recommended fix; spot the rows marked Fixed and verify the linked PR landed.
  5. Form first impressions and request what isn't in the docs. Specific questions about a surface, missing reproducibility information for a finding, additional context on a deferral — the internal review team will produce on demand.

What is in flight at handoff

This section is updated as state changes. As of the publication of Step 12 of the plan (final-plan.md):

  • Open crypto findings. The two Open findings in the published set — the flat-envelope key hierarchy (2.2) and the Argon2id preset on high-entropy metadata-key inputs (2.3) — are spec / implementation hardening items tracked in triage.md with recommended fixes; neither is a launch blocker.
  • Phase 3 (Suite 0x03 default) — design phase, not started. Per Step 13 of the plan. ML-KEM-1024 + XChaCha20-Poly1305 is the production-default cipher suite for Phase 3. The Phase 3 prerequisites in @shieldfive/crypto (crypto#1 through crypto#4) are closed; the application-side rollout shape follows the Phase 2 five-stage pattern.
  • External audit deferral. The audit will be commissioned when product revenue funds it. The internal review is the work that establishes the baseline; the external engagement is expected to extend that baseline rather than replace it.

If you are landing on this document because the external audit engagement is starting, the maintainer to contact is the team behind the bug bounty program at [email protected]. The /security page is the public-facing companion to this document.