fix: verify the build against its own receipt, with the expected mode as an argument (closes #309)
script/verify-build computed its expectation from AUTISTMASK_DEBUG in its own environment, and the Makefile invoked it bare, so an operator with that flag exported who ran the release target got a debug bundle -- every wallet it creates carrying the publicly committed test recovery phrase -- verified green at exit 0. The mode is now the required argument --expect release|debug, with no default and nothing read from the environment; make build passes --expect release on an env -u AUTISTMASK_DEBUG environment and make build-debug passes --expect debug. The flag is deliberately still allowed to reach the compiler, so a shell that has it exported fails make build loudly rather than quietly receiving something other than the release build it asked for. The other half was provenance. 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 as "1 bundle(s) verified". build.js now records every file it emits and writes a receipt of them -- path, sha256, and whether the file is one of the bundles containing constants.js -- to a path the Makefile creates with mktemp per invocation, outside the repo, and deletes afterwards; a receipt path inside dist/ is refused. dist/ is cleared before a build, so it holds only what that build wrote. dist/constants-bundles.txt is gone, and with it the standalone make verify-build target: re-verifying a dist/ out of the dist/ itself is the thing that was broken. verify-build now checks the receipt's shape, then that dist/ contains nothing the build did not emit and no symlinks, then each recorded file's bytes against its digest and each audited bundle's marker against --expect. The guarantee is narrow and README.md states it as such: dist/ is byte for byte the output of the build.js run that just finished. It proves nothing about the honesty of the source tree or of build.js, and offers nothing to a third party holding a dist/. That is signing: #310 script/test-verify-build goes from 18 cases to 39, extended in place: one per demonstrated bypass, the missing/invalid argument cases, an AUTISTMASK_DEBUG=1 environment that the verifier must ignore, debug bundles that must fail --expect release, and four checks that read the make build and make build-debug recipes back out of make -n. The existing failure modes (grep exit-2, find's status, newline and trailing-space paths, symlinked dist/, and the root probe that refuses to count permission cases vacuously) are kept. Verified: make check green (39 suites / 811 tests, 39 verify-build cases, permission cases enabled), and green again inside the pinned image via script/cibuild with --no-cache-filter=check, where the harness runs as root and reports the setpriv runner rather than skipping. Non-vacuity proved by mutation: disabling the digest comparison fails exactly the four bypass cases, removing the dist/ walk fails the eight extra-file and symlink cases, restoring the ambient AUTISTMASK_DEBUG fallback fails the no---expect case, breaking the Makefile recipe fails the wiring cases, and dropping manifest.json from the recorded emissions fails a real make build.
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