build: make verify-build take an explicit expectation and a build receipt (closes #309)
verify-build read its expectation from AUTISTMASK_DEBUG in its own environment and the Makefile invoked it bare, so an operator with that variable exported who ran the release target got an INSECURE debug build — every wallet it creates uses the publicly committed test phrase — verified green, exit 0. It also had no provenance: a 26-byte file containing the right marker string passed, the content script and manifest.json were never inspected, and an entire hand-written dist/ passed. --expect release|debug and --receipt PATH are now both required, with no defaults and nothing read from the environment. build.js records every file it emits with its sha256 and writes the receipt; the Makefile mktemps it outside the repo per invocation with a trap, and build.js refuses a receipt path inside dist/. Verification runs three passes in a load-bearing order — receipt shape, full dist/ walk, then per-file bytes — so an unwalkable subtree cannot make files look absent. dist/constants-bundles.txt, which was an unsigned trust root living inside the tree it vouched for, is gone. What this proves is bounded and stated as such: dist/ is byte-for-byte the output of the build.js run that just finished, within one make build invocation. It proves nothing about the honesty of the source tree or build.js, and nothing to anyone handed a dist/ from elsewhere — that is signing, #310. The standalone make verify-build target is removed because its only input would be dist/ itself, i.e. the artifact vouching for itself. Verified: make check green, test-verify-build 39 cases (was 18), test-e2e 55/55 and test-e2e-firefox 8/8 with make build running uncached inside both images. All four original bypasses now exit 1. Mutations: digests disabled fails exactly 4 cases, dropping the dist/ walk fails exactly 8, restoring the ambient fallback fails exactly 1.
This commit was merged in pull request #330.
This commit is contained in:
32
TODO.md
32
TODO.md
@@ -25,8 +25,8 @@ pre-1.0, working towards the 1.0.0 milestone. Tagged v0.1.0 on 2026-02-27. The
|
||||
milestone is in flight on `next`; its `next` -> `main` PR is
|
||||
[#190](https://git.eeqj.de/sneak/AutistMask/pulls/190). `make check` verified
|
||||
green on `next` at `e9fa8be` on 2026-08-10, and `make build` produces
|
||||
`dist/chrome/` and `dist/firefox/` with every bundle verified to have `DEBUG`
|
||||
compiled off.
|
||||
`dist/chrome/` and `dist/firefox/`, verified against the build's own receipt to
|
||||
be exactly what that build emitted with `DEBUG` compiled off.
|
||||
|
||||
The backlog lives on the
|
||||
[Gitea tracker](https://git.eeqj.de/sneak/AutistMask/issues), which is
|
||||
@@ -44,6 +44,34 @@ but the review is broader than any of them.
|
||||
|
||||
# Completed Steps
|
||||
|
||||
- 2026-08-20: `make build` can no longer hand back a debug build, and
|
||||
`script/verify-build` can no longer be satisfied by bytes the build did not
|
||||
produce ([#309](https://git.eeqj.de/sneak/AutistMask/issues/309)). The
|
||||
verifier used to compute its expectation from `AUTISTMASK_DEBUG` in its own
|
||||
environment, so an operator with that exported who ran the release target got
|
||||
a debug bundle — every wallet it creates carrying the publicly committed test
|
||||
phrase — certified green at exit 0. The expected mode is now the required
|
||||
argument `--expect release|debug`, with no default and nothing read from the
|
||||
environment, and the `Makefile` scrubs the flag from the verifier while
|
||||
deliberately leaving it reaching the compiler, so that shell fails the build
|
||||
loudly instead of quietly getting something other than what it asked for.
|
||||
Provenance was the other half: the check was a marker grep over a file list
|
||||
read back out of `dist/`, so a 26-byte file containing only
|
||||
`autistmask-build-debug=off` verified `ok`, `manifest.json` and the content
|
||||
script that runs on every page were never read at all, and an entire
|
||||
hand-written `dist/` passed. `build.js` now records every file it emits, with
|
||||
its sha256 and whether it is one of the bundles containing `constants.js`,
|
||||
into a receipt whose path the `Makefile` makes fresh per invocation outside
|
||||
the repo and deletes afterwards; `dist/constants-bundles.txt` is gone, and
|
||||
`dist/` is cleared before a build so it holds only what that build wrote. The
|
||||
standalone `make verify-build` target went with it: re-verifying a `dist/`
|
||||
from the `dist/` itself is the thing that was broken. What this establishes is
|
||||
narrow and stated as such in README.md — `dist/` is byte for byte the output
|
||||
of the `build.js` run that just finished — and it is not signing, which is
|
||||
[#310](https://git.eeqj.de/sneak/AutistMask/issues/310).
|
||||
`script/test-verify-build` grew from 18 cases to 39, including one per
|
||||
demonstrated bypass and the `make -n` read-back that proves the recipes pass
|
||||
the mode as an argument.
|
||||
- 2026-08-20: A hostile ERC-20 symbol no longer renders as live HTML in the
|
||||
popup ([#307](https://git.eeqj.de/sneak/AutistMask/issues/307)). A token
|
||||
symbol is whatever the contract's `symbol()` returns, the block explorer
|
||||
|
||||
Reference in New Issue
Block a user