Postern Labs
MAINNET BETA. Unaudited · relaxed k=4 regime (trivially forgeable) · k=8 hardening reverted, re-activating with a difficulty fix · very few nodes, 51%-attackable · not a security · for evaluation — not to protect real secrets yet. Full disclaimer →

Internal adversarial review · not a third-party audit

Security review & test-suite report.

An honest accounting of an internal adversarial code review and the real automated test suites behind it — what we tested, what held up, and the real bugs it found and fixed. This is not a third-party security audit. Every Postern product remains UNAUDITED.

Read this before the numbers below

  • This is an INTERNAL review, not an external audit. No third-party security firm has examined this code. A third-party audit is contracted but not done yet — until it is delivered, everything here stays UNAUDITED. What follows is (a) a self-directed adversarial code review and (b) the real counts from re-running the automated test suites on this host. Neither is a substitute for independent, professional audit.
  • We show the bugs we found, not just the tests that pass. A pile of passing tests proves little on its own — a suite that never tried to break anything would pass too. So this page names the real defects the review surfaced, on real branches, with real fixes and real regression tests, alongside the coverage. That is the honest version of a clean bill: not "nothing was found," but "here is exactly what was found, and here is the fix."
  • Everything here inherits every standing disclosure on this site: mainnet beta, reference-prototype, 51%-attackable, not a security. Passing tests and a clean review are not a certification. Full disclaimer →

What this is — and is not

An internal review and a test count. Nothing more is claimed.

What it is: a self-directed adversarial code review across the subsystems below, plus the actual, re-run counts from each subsystem's automated HOST test suite (the tests that run on a developer machine or CI — no phone, no hardware attestor, no box required). Where a bug was found, it was fixed and a regression test was added so it cannot silently return.

What it is not: a third-party security audit; a penetration test by an outside firm; a formal verification; a certification of any kind; a claim that the software is "secure," "hardened," or "production-ready." None of those words apply here. UNAUDITED is the correct word, and it is the one this page uses.

The review ran as a wave of specialized adversarial passes over the currently-integrated feature branches (see Methodology) — not one branch that contains every fix merged together yet; that consolidation is itself a listed open item. Each number in the table below states which branch it was measured on.

Test coverage — real, re-run counts

1427 host tests, re-run on this host, tallied by subsystem.

Every number below was produced by actually re-running the suite (cargo test / node --test / the project's own runner script) in this session, not carried over from an old log. Counts are what the suite itself reports as passed. One suite — the reproducible-build two-builder check — has a single test that only passes on a host with Nix installed; this host has none, so it fails honestly rather than being skipped or faked. That is disclosed, not hidden.

Rust (cargo test) — 370 passed

Crate / appPassedBranch measured onWhat it exercises
postern-seal-companion133integ/noporis-porogAttestation verifier: SNP report chain (VCEK→ASK→ARK), CRL freshness/revocation, TPM2 PCR-vector replay, TCB-floor enforcement, constant-time checks
noporis-bridge-glue146integ/noporis-porogDual-persona crossing/bridge: fail-closed gate negatives, session-id domain separation, consent-record signature + revocation, writer-lock CLI (steal/crash recovery)
terem-gate41fix/terem-disjointTerem guest-sandbox consent tier: 5 guest↔host bridges, path-disjointness (symlink/traversal evasion), single-use grant consumption, target-pin enforcement
postern-core + postern-vault20integ/noporis-porogCanonical AEAD seal, Argon2id KDF determinism, context-bound vault blobs, corrupt-serialization rejection
postern-courier17integ/noporis-porogML-KEM-1024 sealed drop, signed-drop authentication, anti-replay window, wrong-recipient / tampered-signature rejection
desktop/src-tauri (terem lib)13integ/terem-fixesQMP guest-runtime: binary resolution, allowlist accept/reject (incl. case/substring evasion), the disk_path→-drive injection fix, create/destroy lifecycle

Node / JS (node --test / project runners) — 1056 passed (1 environment-only fail — see note)

SuitePassedBranch measured onWhat it exercises
Depot (test-depot.mjs, repo-poc, repro-verifier, test-repo-trust.mjs, test-core.mjs)86 / 87 · 1 env-failfix/depot-replayMulti-repo trust states, CRL sign/verify/freshness/repo-binding, reproducible-build record binding, key-rotation forgery resistance, two-builder divergence detection
gramota-kyc (6 files: core, OCR seam, D&B client, review seam, issuance, inline parity)102roadmap/buckets-integrateFail-closed OCR (never fabricates a read), LoA ladder, D&B outage-vs-hard-fail matrix, KYC-bound token issuance
noporis-gate (test-store.mjs)66integ/noporis-porogGate-store persistence: foreign schema/version pinning, sealed-wallet pin immutability, kill-switch direction masking
porog-crossprofile (reconcile-kernel)314integ/noporis-porogCross-profile reconciliation kernel — hardened from 102 to 314 host tests over the D1–D5 review passes
sloboda-gate (test-store.mjs + test-gated.mjs)204roadmap/buckets-integrateGate state store (31) + gated-launch enforcement (173): fail-closed launch decisions, consent-state persistence
consent-spine (test-spine.mjs)117integ/noporis-porogShared consent-contract schema/state-machine: grant expiry, revocation-as-never-given, cross-app consent shape parity
comms (app self-check, compliance self-check, dotfile-guard)78roadmap/buckets-integrateEnterprise comms: retention/legal-hold, DSAR fail-closed identity check, breach-assessment 72h clock, hash-chained audit tamper detection
SDK-parity test-core.mjs (9 apps: Vedetta, Sarto, Bloch Wallet, Tolmach, Consiglio, Sotto, Gramota, Chiave, Tolmach-sub)89roadmap/buckets-integrateReal Argon2id/XChaCha20 SDK-core dispatch vs. labelled PBKDF2/AES-GCM stand-in, fail-closed cross-tab opens, no silent downgrade

The 1 environment-only fail: repro-verifier's two-builder check includes a test that asserts this host genuinely has no Nix installed (proving the script is real, not a simulation) — it fails by design on a host without Nix, which this build host is. It is not a code defect; it is reported here rather than silently skipped.

On the number itself: an earlier internal estimate cited "373+ tests" — a rough sum across a shorter list of headline suites. Re-running and tallying every individual assertion each suite actually reports (several suites, like the Porog reconcile kernel, sloboda-gate, consent-spine, and the 9-app SDK-parity set, carry many more discrete assertions than that estimate captured) gives the real, higher total above. We report the number we measured, not the number we expected.

Methodology

A 20-agent adversarial wave, four kinds of pass.

The review ran as roughly twenty parallel, specialized adversarial passes over the integrated feature branches, each with a narrow mandate:

  • A crypto-usage sweep — every call site touching Ed25519, XChaCha20-Poly1305, ML-KEM, Argon2id, and the SNP/TPM attestation chain, checked for nonce reuse, missing authentication, wrong key sizes, and non-constant-time comparisons on secret material.
  • A fail-closed / test-integrity sweep (mutation testing) — deliberately break the code under test (flip a comparison, remove a check, widen a permission) and confirm the corresponding test goes red. A test suite that stays green when the code is broken is worse than no test suite: it is a false assurance. This is how several of the "found & fixed" bugs below were actually located — a mutation that should have been caught wasn't, which is what sent a reviewer into that code path in the first place.
  • A repo-wide honesty sweep — the same trust-label discipline this site enforces mechanically (scripts/check-trust-labels.sh): hunting for attestation-grade or audited/secure/hardened language bleeding onto a surface that hasn't earned it.
  • Per-subsystem adversarial red-teams — one pass per subsystem (Depot, Terem, NoporIS/Porog, gramota-kyc, sloboda-gate, comms) attempting the specific attacks that subsystem's threat model implies: record replay, consent forgery, path-traversal evasion, cross-repo CRL confusion, and so on.

Every fix below shipped with a proof-of-concept demonstrating the bug, a patch, and a new regression test — the mutation-testing discipline applied to the fix itself: the new test must fail against the old code and pass against the new one.

What held up

The crypto primitives were found sound. No critical primitive break.

The crypto-usage sweep did not surface a break in any core primitive. Specifically, across the crates above:

  • Real, standard primitives — Ed25519 signatures, XChaCha20-Poly1305 AEAD, Argon2id at the RFC 9106 tier, ML-KEM-1024 (FIPS-203) for Courier's sealed drop — not custom or home-rolled cryptography.
  • CSPRNG nonces — nonce generation for the AEAD constructions goes through the OS CSPRNG, not a counter or a weak PRNG; no nonce-reuse pattern was found.
  • Constant-time comparison on secret material — the checks that matter (signature verification inputs, key material) use constant-time equality, not a branching byte-compare.
  • Fail-closed defaults — the review's mutation-testing pass specifically hunts for fail-open defaults (a missing check that defaults to "allow"); the gate, consent, and audit code paths reviewed default to refusal, not permission, on an unrecognized or malformed input.

"Sound" describes what the review did not break, on the branches it reviewed, at this point in time — it is not a certification, and it does not extend to code the review did not cover. See known open items below for what has not yet been exercised at all.

What was found & fixed

The real bugs the review surfaced — named, not hidden.

This is the part a marketing page would omit. We include it because a review that found nothing worth naming isn't credible, and a review that names its findings — with the PoC, the fix, and the regression test — is the honest version of "we looked."

Depot 4 findings, fixed

ATTESTED-record replay (critical): a genuinely signed, trusted reproducible-build PASS record for one app could be copy-pasted onto a different app or version and still earn the ATTESTED badge — neither verifier checked the record's own app_id/version against the catalog entry it was attached to. CRL not repo-bound: a per-repo revocation list was authenticated only by signature, never checked against the repo_id being queried — two repos sharing an operator key let an attacker replay one repo's (e.g. empty) CRL as another's, suppressing revocations. Case-sensitive badge-strip: a dishonest repo could dodge the proprietary-app hosting/checksum strip with class:"Proprietary" or foss:"false" (the string). Plus an unsigned-CRL-accepted gap and a same-version CRL tie that could silently un-revoke. All four fixed, with regression tests (test-depot.mjs 17→26, repo-poc crl.test.mjs 16→21, repro-verifier record.test.mjs 9→12).

Terem 4 findings, fixed

QMP disk_path→-drive injection: the v1 red-team fix — terem_qmp is not raw QMP passthrough; an exact-match allowlist (query-status, query-name, query-version, qom-list, system_powerdown) is checked fail-closed before anything reaches the socket, rejecting drive_add, blockdev-add, device_add, and other commands that could hand a guest a raw host block-device handle. Consent-gate target-pin bypass: ConsentLedger::authorize accepted a missing target for SharedFolder/Usb crossings, silently skipping the pinned-path/device re-check and authorizing with zero verification — now refused up front. Single-use not self-enforced: a one-shot grant only retired when a separate commit_use() call happened, so skipping that call made it replayable — authorize() now atomically consumes it. Path-disjointness evasion: ancestor-symlink resolution and relative-path anchoring were incomplete, letting a crafted path evade the disjointness check. All fixed with regression tests (terem-gate: 32→41 tests).

NoporIS 2 findings, fixed

from_persona spoofing: a crossing's claimed origin persona was trusted as sent, rather than cross-checked against the receiving endpoint's own derived origin — a compromised far side could mislabel which world a crossing came from. Fixed: the receiver now pins its own from_persona at construction (derived from the pairing/lane, never from the crossing itself) and rejects any claimed origin that doesn't match. Receiver-side size cap: the payload ceiling (16 KiB) was enforced on the sender's courtesy check but not re-verified on the opened payload at the receiver — now re-checked at the point the sealed frame is actually opened, closing the path where a sender's own cap could be bypassed.

Every fix above shipped with its own commit, PoC, and regression test on the branch named in the coverage table; none of these branches has silently dropped a test count since the fix — each is a strict increase in tests passed, which is exactly what a real regression test should produce.

Known open items — tracked, not hidden

What the review did not close.

Still open

  • SNP VCEK temporal-validity gap. The attestation verifier authenticates the VCEK→ASK→ARK certificate chain and checks revocation via CRL, but does not check X.509 notBefore/notAfter validity windows on any certificate in the chain. A VCEK past its own expiry (or presented before its validity starts) is not caught by that check alone. Documented in the crate's own hardware runbook; lower severity than a revocation gap (AMD's roots are long-lived by design), but open.
  • Two-builder reproducible-build verification is single-signer today. The repro-verifier's design is a two-independent-builder comparison, but only one builder identity is wired up in this environment (the check that would exercise the second builder fails here for lack of Nix — see the coverage note above). Bit-for-bit reproduction across two independent builders is not yet demonstrated end-to-end.
  • Some doc-vs-doc reconciliations remain. A handful of design documents across the NoporIS/Porog and Terem specs describe behavior slightly ahead of, or slightly divergent from, what the current code implements; these are tracked as documentation debt, not code bugs, but they mean a reader of the docs alone should not assume 1:1 parity with the shipped behavior.
  • Box/hardware-gated verification has not run on real hardware. No OS boot or attestation flow in this review has been verified on physical hardware — SNP attestation, StrongBox key-attestation, and the OS boot harnesses have run against fixtures, vectors, and QEMU, never a physical box. This mirrors the site's standing OS-image disclosure: built and signed is not the same as hardware-tested.
  • The fixes above live on separate feature/integ branches, not yet one consolidated branch. Depot, Terem, and NoporIS/Porog hardening each landed on their own branch (named in the coverage table); a single branch carrying all of it merged together is a tracked follow-up, not yet done.

The standing rails

The same disclosures as everywhere else on this site.

unaudited mainnet beta reference prototype verify, don't trust

This page does not change any of them. UNAUDITED means exactly what it says until a third-party audit is delivered. Mainnet beta is a designation, not a security claim. Reference-prototype describes software built to demonstrate a design, not certified for production. And verify, don't trust is the standing instruction: build it from source, read the tests yourself, re-run the suites — don't take this page's word for any of it. Full disclaimer →