Skip to content

fix(receipts): seal and verify on a clean install; add a no-URL first command - #684

Merged
DealAppSeo merged 4 commits into
mainfrom
feat/cc-2026-11-08-first-value
Nov 8, 2026
Merged

DealAppSeo merged 4 commits into
mainfrom
feat/cc-2026-11-08-first-value

Conversation

@DealAppSeo

Copy link
Copy Markdown
Owner

trustshell demo works on a clean install

Installed from a packed tarball, trustshell demo exited 3, because the receipt hash needed the optional ethers peer. kernelReceiptHash now uses @noble/hashes 1.3.2, the version ethers already pins. Sealing and verifying a receipt now work without ethers. Hashing kernel arguments is unchanged and still needs it.

This adds a direct dependency to a published package, so it needs an owner decision.

Output is unchanged: tests/kernel-receipt-hash-no-ethers.test.ts compares it with ethers byte for byte, including non-ASCII text.

A first command with no URL of your own

One line in the README's opening paragraph runs against a pinned run and works as written in bash, zsh and PowerShell. It is inline on purpose: tests/readme-first-screen pins the first fenced recipe as the path a stranger copies, so that stays first.

Evidence

  • From a tarball of the committed dist/, with no ethers and an empty environment: demo exits 0, and a passive tracer recorded zero connections.
  • Tampered and wrong-key receipts exit 1. A separate program, using ethers keccak and Node's Ed25519, agrees.
  • The README command was measured on 1.8.1 from npm in bash and Windows PowerShell on 2026-11-08: CONTRADICTED, exit 1.
  • The 8 suites that fail on this machine match the untouched base by test name. The whole suite last ran one commit before the README and dist/ commit.

Not published. npm publish stays with the owner.

🤖 Generated with Claude Code

DealAppSeo and others added 3 commits November 8, 2026 04:52
trustshell demo exited 3 on a fresh install from the packed tarball, because
the receipt hash needed the optional ethers peer. The hash now comes from
@noble/hashes 1.3.2, the version ethers already pins. Output is unchanged:
a test compares it with ethers byte for byte. Args hashing is not touched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…r own

Measured on 1.8.1 from npm in bash and Windows PowerShell on 2026-11-08.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… inline

tests/readme-first-screen pins the first fenced recipe as the SUPPORTED path a
stranger copies, and the previous commit displaced it. Also rebuilds dist for
the receipt hash change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
trustshell-landing Ready Ready Preview Nov 8, 2026 10:10pm UTC

Request Review

@DealAppSeo
DealAppSeo marked this pull request as ready for review November 8, 2026 17:02
@strix-security

strix-security Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

Strix Security Review

✅ No open security findings.

PR summary: Makes receipt sealing and verification work on a clean install by computing the receipt's keccak256 hash with `@​noble/hashes` (now a direct dependency) instead of the optional `ethers` peer, rebuilds the committed `dist/`, adds a test pinning the hash against ethers, adds a no-setup example command to the README, and moves two build output directories into `node_modules/.cache` so the compiled CLI resolves its runtime dependencies.

Review summary

No security findings. The receipt-hash swap to @noble/hashes 1.3.2 is byte-for-byte equivalent to the previous ethers implementation for every reachable input (canonical JSON escapes lone surrogates, so the one primitive-level divergence in surrogate handling is unreachable), the 17 conformance vectors still reproduce, and dropping the loadEthers call removes only a refusal — integrity is now actually recomputed on a cold install instead of being skipped. The committed dist/ is byte-identical to a deterministic tsc rebuild of the changed src/, and the freshness gate that enforces this was not touched. The new dependency was already present in the lockfile as an ethers transitive with the same integrity hash, is exact-pinned and statically imported, and has no reachable advisory. The two build-output relocations into node_modules/.cache strengthen rather than weaken the egress check: from the OS tmpdir the compiled CLI could not resolve its runtime dependencies, so the check was failing loudly and verifying nothing; all failure modes still exit non-zero, and the new paths are __dirname-derived with no user input, no shell, and no arbitrary write or delete.

Ruled out (6)
  • Does the committed dist/ diverge from a rebuild of the changed src/, shipping unreviewed code to npm consumers?
    A full `tsc -p tsconfig.sdk.json` rebuild diffed against `dist/` produced zero differences, and the unmodified `tests/sdk-dist-fresh.test.ts` gate was shown to catch even a one-line injection.
  • Does moving the egress-check build output into node_modules/.cache weaken the egress verification or allow an attacker-controlled module to be resolved?
    The relocation strengthens the check (from tmpdir the compiled CLI could not resolve its dependencies and every pin failed), node_modules is gitignored so nothing there is committable, and the new paths are `__dirname`-derived with array argv and no shell.
  • Is the @​noble/hashes keccak_256 swap equivalent to ethers keccak256, including for non-ASCII and lone-surrogate input?
    Both implementations agree on all 17 conformance vectors and on lone surrogates, because `kernelCanonicalJson` goes through `JSON.stringify`, which escapes them before either encoder sees them.
  • Does removing the loadEthers call from kernelReceiptHash remove a security check?
    It removed only the MissingDependencyError refusal; every caller still performs the hash comparison, so a cold install now verifies integrity where it previously reported NOT_CHECKED.
  • Does the new @​noble/hashes 1.3.2 direct dependency introduce a supply-chain or known-CVE risk?
    The version was already in the lockfile as an ethers transitive with the same integrity hash, is exact-pinned and statically imported, and the only advisory covering it needs an options object that `keccak_256` is never called with.
  • Does the new README line's unpinned `npx @​hyperdag/trustshell@​latest` command create a supply-chain risk?
    It is a documentation change that repeats a pattern the README already used in two other places, so it introduces no new runtime behaviour.
Review history (2)
  • Review 2 · b4c8113 · Nov 8 22:13 UTC · Nothing new
  • Review 1 · f569e43 · Nov 8 17:07 UTC · Nothing new

Review 2 on this PR · b4c8113 · requested Nov 8 22:09 UTC on a new commit


Reviewed by Strix
Re-run review · Configure security review settings

@strix-security strix-security Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the receipt-hashing swap, the new dependency, the committed dist/ rebuild, the README line and the new test suite. kernelReceiptHash now calls @noble/hashes' keccak_256 directly — the same function ethers' keccak256 wraps — and I confirmed byte-identical output on non-ASCII input and on all 17 conformance vectors, with the committed dist/ reproducing exactly from a fresh tsc build of the changed src/. Removing the loadEthers call removes only a refusal, never a control: tampered, wrong-key and unpinned receipts still fail closed, and hashKernelArgs still requires ethers. The added dependency is exact-pinned, dedupes with ethers' own pin, and has no advisory. The lint items reached from the changed files (uncaught kernel_receipt handler, --passWithNoTests publish gate, provenance-less runtime dependency, PR-writable dist freshness gate, uncleaned backend strings in CLI output) are pre-existing and are neither introduced nor widened by this diff. No security issues found.


Reviewed by Strix
Configure security review settings

The egress check and the learn-hook suite compiled the CLI into the OS
temp directory. Nothing there can find node_modules, so once the CLI had
a real runtime dependency (@noble/hashes) every command exited 1 with no
output. Build under node_modules/.cache, which is how an install lays it
out. The assertions are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@strix-security strix-security Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No security findings. The receipt-hash swap to @noble/hashes 1.3.2 is byte-for-byte equivalent to the previous ethers implementation for every reachable input (canonical JSON escapes lone surrogates, so the one primitive-level divergence in surrogate handling is unreachable), the 17 conformance vectors still reproduce, and dropping the loadEthers call removes only a refusal — integrity is now actually recomputed on a cold install instead of being skipped. The committed dist/ is byte-identical to a deterministic tsc rebuild of the changed src/, and the freshness gate that enforces this was not touched. The new dependency was already present in the lockfile as an ethers transitive with the same integrity hash, is exact-pinned and statically imported, and has no reachable advisory. The two build-output relocations into node_modules/.cache strengthen rather than weaken the egress check: from the OS tmpdir the compiled CLI could not resolve its runtime dependencies, so the check was failing loudly and verifying nothing; all failure modes still exit non-zero, and the new paths are __dirname-derived with no user input, no shell, and no arbitrary write or delete.


Reviewed by Strix
Configure security review settings

@DealAppSeo
DealAppSeo merged commit a25cb44 into main Nov 8, 2026
10 checks passed

This branch was successfully deployed

1 active deployment
Preview — b4c81131 Deployed Nov 8, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant