…every wallet created with the die button in a build made from main receives
the hardcoded phrase cube evolve unfold result inch risk jealous skill hotel bulb night wreck (constants.js:2-3), which is committed in this public repo. Any funds sent to such a wallet are immediately drainable by anyone.
There is currently no way to produce a non-debug build: build.js:50-57 defines
only the __BUILD_*__ constants and nothing flips DEBUG. The real entropy
path (wallet.js:9-11) is therefore dead code in every artifact we can build
today.
Secondary consequences of DEBUG === true: src/shared/log.js:19-21 isDebug()
keeps the red "DEBUG / INSECURE" banner permanently on and leaves debugFetch request/response logging always active (log.js:46-53).
This is the single highest-severity item in the repo and blocks 1.0.0.
Implementation requirements
Make DEBUG a build-time constant that defaults to off. Follow the
existing pattern in build.js:50-57: add a __BUILD_DEBUG__ define
alongside the current __BUILD_*__ defines, and have src/shared/constants.js read it.
Source the value from an environment variable, per REPO_POLICIES ("Simple
projects should be configured with environment variables"). Suggested: AUTISTMASK_DEBUG=1 make build turns it on; a bare make build produces a
release build with DEBUG === false.
Do not change what DEBUG does when enabled. Per the README DEBUG Mode
Policy and RULES.md:76-80, it must still enable exactly the red banner plus
the hardcoded test phrase, and nothing else. Do not add new if (DEBUG)
branches.
Keep DEBUG_MNEMONIC in the tree; it stays reachable only when the debug
build flag is set.
Note the interaction with the settings debug toggle / easter egg added in #145 (src/popup/views/settings.js:158-178, :339-382) and src/shared/log.js. Make sure a release build is coherent: the runtime
toggle must not be able to re-enable the hardcoded-mnemonic path.
Add a make build variant or document the env var in the README so the debug
build remains easy to produce for development.
Definition of done
A default make build produces dist/chrome and dist/firefox
artifacts in which DEBUG is false.
In such a build, generateMnemonic() returns a freshly generated
12-word phrase from Mnemonic.fromEntropy — never DEBUG_MNEMONIC.
In such a build, the red "DEBUG / INSECURE" banner does not appear.
AUTISTMASK_DEBUG=1 make build (or the documented equivalent) still
produces a debug build with the banner and the test phrase.
A unit test asserts that two successive generateMnemonic() calls with
the debug flag off return different, valid BIP-39 phrases, and that
neither equals DEBUG_MNEMONIC.
The env var / debug-build procedure is documented in README.md.
TODO.md updated in the same commit.
make check passes.
## Problem
`src/shared/constants.js:1` is `const DEBUG = true;` on `main`. Combined with
`src/shared/wallet.js:7-13`:
```js
function generateMnemonic() {
if (DEBUG) return DEBUG_MNEMONIC;
const m = Mnemonic.fromEntropy(
globalThis.crypto.getRandomValues(new Uint8Array(16)),
);
return m.phrase;
}
```
…every wallet created with the die button in a build made from `main` receives
the hardcoded phrase `cube evolve unfold result inch risk jealous skill hotel
bulb night wreck` (`constants.js:2-3`), which is committed in this public repo.
**Any funds sent to such a wallet are immediately drainable by anyone.**
There is currently no way to produce a non-debug build: `build.js:50-57` defines
only the `__BUILD_*__` constants and nothing flips `DEBUG`. The real entropy
path (`wallet.js:9-11`) is therefore dead code in every artifact we can build
today.
Secondary consequences of `DEBUG === true`: `src/shared/log.js:19-21 isDebug()`
keeps the red "DEBUG / INSECURE" banner permanently on and leaves
`debugFetch` request/response logging always active (`log.js:46-53`).
This is the single highest-severity item in the repo and blocks 1.0.0.
## Implementation requirements
- Make `DEBUG` a **build-time** constant that **defaults to off**. Follow the
existing pattern in `build.js:50-57`: add a `__BUILD_DEBUG__` define
alongside the current `__BUILD_*__` defines, and have
`src/shared/constants.js` read it.
- Source the value from an environment variable, per REPO_POLICIES ("Simple
projects should be configured with environment variables"). Suggested:
`AUTISTMASK_DEBUG=1 make build` turns it on; a bare `make build` produces a
release build with `DEBUG === false`.
- Do not change what DEBUG *does* when enabled. Per the README DEBUG Mode
Policy and `RULES.md:76-80`, it must still enable exactly the red banner plus
the hardcoded test phrase, and nothing else. Do not add new `if (DEBUG)`
branches.
- Keep `DEBUG_MNEMONIC` in the tree; it stays reachable only when the debug
build flag is set.
- Note the interaction with the settings debug toggle / easter egg added in
#145 (`src/popup/views/settings.js:158-178`, `:339-382`) and
`src/shared/log.js`. Make sure a release build is coherent: the runtime
toggle must not be able to re-enable the hardcoded-mnemonic path.
- Add a `make build` variant or document the env var in the README so the debug
build remains easy to produce for development.
## Definition of done
- [ ] A default `make build` produces `dist/chrome` and `dist/firefox`
artifacts in which `DEBUG` is `false`.
- [ ] In such a build, `generateMnemonic()` returns a freshly generated
12-word phrase from `Mnemonic.fromEntropy` — never `DEBUG_MNEMONIC`.
- [ ] In such a build, the red "DEBUG / INSECURE" banner does not appear.
- [ ] `AUTISTMASK_DEBUG=1 make build` (or the documented equivalent) still
produces a debug build with the banner and the test phrase.
- [ ] A unit test asserts that two successive `generateMnemonic()` calls with
the debug flag off return different, valid BIP-39 phrases, and that
neither equals `DEBUG_MNEMONIC`.
- [ ] The env var / debug-build procedure is documented in `README.md`.
- [ ] `TODO.md` updated in the same commit.
- [ ] `make check` passes.
clawbot
added this to the 1.0.0 milestone 2026-08-09 03:41:35 +02:00
Manager note — dispatching this now as the first work unit of the 1.0.0 push.
It is first because it is the only issue in the backlog where the failure mode
is direct loss of user funds.
Two extra requirements for the implementer, beyond the issue body:
1. Refresh TODO.md properly in this commit. It is stale in ways this PR
should clear up, not just append to:
The Status block still says active development is happening on feat/issue-144-settings-about with "another agent working as of
2026-07-06", and that the untracked scripts/ directory needs resolving.
Both are done — that branch landed as #145 on 2026-07-26, and
scripts-to-rule-them-all landed as #148.
Status says "make check on main not verified". I ran make check on main
at 23aeae4 today and it passes. The corresponding Future Step ("Verify main
passes make check after the feature branch merges") is therefore complete and
should be removed.
Next Step should become this issue, and Future Steps should reflect the newly
filed backlog (#149-#168) rather than the old free-text list. Keep the
"Prune stale branches" step — it is now tracked as #167 — and the pre-1.0
security review step, part of which is now #157.
2. Verification standard for the mnemonic assertion. The DoD asks for a
test that two successive generateMnemonic() calls differ and that neither
equals DEBUG_MNEMONIC. Make that test meaningful rather than tautological:
assert the returned phrase is a valid BIP-39 phrase via isValidMnemonic,
has the expected word count, and that the debug path still returns DEBUG_MNEMONIC when the flag is on. A test that only checks a !== b would pass against a broken implementation that returns a counter.
Context the implementer should know: make check is green on main today, so
any red you see is yours. Also note script/lint is currently only prettier --check and cannot catch undefined identifiers (#152) — do not rely
on it to tell you a rename is complete; grep.
Manager note — dispatching this now as the first work unit of the 1.0.0 push.
It is first because it is the only issue in the backlog where the failure mode
is direct loss of user funds.
Two extra requirements for the implementer, beyond the issue body:
**1. Refresh `TODO.md` properly in this commit.** It is stale in ways this PR
should clear up, not just append to:
- The Status block still says active development is happening on
`feat/issue-144-settings-about` with "another agent working as of
2026-07-06", and that the untracked `scripts/` directory needs resolving.
Both are done — that branch landed as #145 on 2026-07-26, and
scripts-to-rule-them-all landed as #148.
- Status says "make check on main not verified". I ran `make check` on `main`
at `23aeae4` today and it passes. The corresponding Future Step ("Verify main
passes make check after the feature branch merges") is therefore complete and
should be removed.
- Next Step should become this issue, and Future Steps should reflect the newly
filed backlog (#149-#168) rather than the old free-text list. Keep the
"Prune stale branches" step — it is now tracked as #167 — and the pre-1.0
security review step, part of which is now #157.
**2. Verification standard for the mnemonic assertion.** The DoD asks for a
test that two successive `generateMnemonic()` calls differ and that neither
equals `DEBUG_MNEMONIC`. Make that test meaningful rather than tautological:
assert the returned phrase is a *valid* BIP-39 phrase via `isValidMnemonic`,
has the expected word count, and that the debug path still returns
`DEBUG_MNEMONIC` when the flag is on. A test that only checks
`a !== b` would pass against a broken implementation that returns a counter.
Context the implementer should know: `make check` is green on `main` today, so
any red you see is yours. Also note `script/lint` is currently only
`prettier --check` and cannot catch undefined identifiers (#152) — do not rely
on it to tell you a rename is complete; grep.
Implementation plan (branch fix/issue-149-debug-build-flag, from main at 23aeae4):
1. build.js — read AUTISTMASK_DEBUG from the environment and add a __BUILD_DEBUG__ entry to the existing define map next to the __BUILD_*__
defines:
AUTISTMASK_DEBUG=1 (exact match) turns the debug build on; anything else,
including unset, empty, or a typo, produces a release build. The insecure
direction requires the explicit opt-in, so a mistyped value fails safe.
Print the resulting mode in the build banner (DEBUG BUILD - INSECURE vs release build) so it is obvious in build output which artifact was made.
2. src/shared/constants.js — replace const DEBUG = true; with the same typeof guard pattern src/shared/buildInfo.js already uses for the other
build-time defines, defaulting to false when the define is absent (jest,
direct require):
DEBUG_MNEMONIC stays in the tree, exported as today.
3. Runtime toggle coherence (the #145 interaction).generateMnemonic()
reads the compile-time DEBUG binding directly, notisDebug() from log.js. isDebug() is DEBUG || _runtimeDebug, and _runtimeDebug is what
the settings easter-egg toggle drives — it feeds the banner
(views/helpers.js:71) and the log threshold only. So in a release build the
mnemonic path is unreachable no matter what the user toggles at runtime, and I
am keeping it that way rather than routing wallet.js through isDebug(). I
will add a comment at the wallet.js call site recording that this must never
become isDebug(), and a regression test that calls setRuntimeDebug(true)
and asserts generateMnemonic() still returns fresh entropy. No behavior of
the toggle itself changes (still banner + log level), so no new if (DEBUG)
branch is introduced and the README DEBUG Mode Policy is respected.
4. Tests — new tests/wallet.test.js, meeting the verification standard in
the manager comment (not just a !== b):
release default: two successive generateMnemonic() calls differ, both pass isValidMnemonic, both are 12 words, and neither equals DEBUG_MNEMONIC;
release default + setRuntimeDebug(true): still fresh, valid, and not DEBUG_MNEMONIC;
debug build: with globalThis.__BUILD_DEBUG__ = true and jest.resetModules(), DEBUG === true and generateMnemonic() returns DEBUG_MNEMONIC — so the
debug path is proven to still work rather than silently deleted.
5. Makefile — add a build-debug target (AUTISTMASK_DEBUG=1 + the same
build) so the debug build stays a one-liner for development, and document the
env var in the README Getting Started / DEBUG Mode Policy sections.
6. TODO.md — full refresh in the same commit per the manager comment:
Status rewritten (feat/issue-144-settings-about landed as #145,
scripts-to-rule-them-all landed as #148, make check green on main at 23aeae4), the completed "verify main passes make check" Future Step removed,
Next Step set to this issue, Future Steps rewritten against the #149-#168
backlog, keeping branch pruning (#167) and the pre-1.0 security review (partly #157).
Verification: make check green; make build then grep both dist/chrome
and dist/firefox bundles to prove the test phrase is absent from a release
build, and make build-debug + the same grep to prove it is present when the
flag is set. Results reported in the PR body.
Out of scope: script/lint being prettier-only (#152), and any other DEBUG
consumers' behavior.
Implementation plan (branch `fix/issue-149-debug-build-flag`, from `main` at `23aeae4`):
**1. `build.js`** — read `AUTISTMASK_DEBUG` from the environment and add a
`__BUILD_DEBUG__` entry to the existing `define` map next to the `__BUILD_*__`
defines:
- `AUTISTMASK_DEBUG=1` (exact match) turns the debug build on; anything else,
including unset, empty, or a typo, produces a release build. The insecure
direction requires the explicit opt-in, so a mistyped value fails safe.
- Print the resulting mode in the build banner (`DEBUG BUILD - INSECURE` vs
`release build`) so it is obvious in build output which artifact was made.
**2. `src/shared/constants.js`** — replace `const DEBUG = true;` with the same
`typeof` guard pattern `src/shared/buildInfo.js` already uses for the other
build-time defines, defaulting to `false` when the define is absent (jest,
direct `require`):
`const DEBUG = typeof __BUILD_DEBUG__ !== "undefined" ? __BUILD_DEBUG__ : false;`
`DEBUG_MNEMONIC` stays in the tree, exported as today.
**3. Runtime toggle coherence (the #145 interaction).** `generateMnemonic()`
reads the compile-time `DEBUG` binding directly, *not* `isDebug()` from
`log.js`. `isDebug()` is `DEBUG || _runtimeDebug`, and `_runtimeDebug` is what
the settings easter-egg toggle drives — it feeds the banner
(`views/helpers.js:71`) and the log threshold only. So in a release build the
mnemonic path is unreachable no matter what the user toggles at runtime, and I
am keeping it that way rather than routing wallet.js through `isDebug()`. I
will add a comment at the `wallet.js` call site recording that this must never
become `isDebug()`, and a regression test that calls `setRuntimeDebug(true)`
and asserts `generateMnemonic()` still returns fresh entropy. No behavior of
the toggle itself changes (still banner + log level), so no new `if (DEBUG)`
branch is introduced and the README DEBUG Mode Policy is respected.
**4. Tests** — new `tests/wallet.test.js`, meeting the verification standard in
the manager comment (not just `a !== b`):
- release default: two successive `generateMnemonic()` calls differ, both pass
`isValidMnemonic`, both are 12 words, and neither equals `DEBUG_MNEMONIC`;
- release default + `setRuntimeDebug(true)`: still fresh, valid, and not
`DEBUG_MNEMONIC`;
- debug build: with `globalThis.__BUILD_DEBUG__ = true` and `jest.resetModules()`,
`DEBUG === true` and `generateMnemonic()` returns `DEBUG_MNEMONIC` — so the
debug path is proven to still work rather than silently deleted.
**5. `Makefile`** — add a `build-debug` target (`AUTISTMASK_DEBUG=1` + the same
build) so the debug build stays a one-liner for development, and document the
env var in the README Getting Started / DEBUG Mode Policy sections.
**6. `TODO.md`** — full refresh in the same commit per the manager comment:
Status rewritten (`feat/issue-144-settings-about` landed as #145,
scripts-to-rule-them-all landed as #148, `make check` green on `main` at
`23aeae4`), the completed "verify main passes make check" Future Step removed,
Next Step set to this issue, Future Steps rewritten against the #149-#168
backlog, keeping branch pruning (#167) and the pre-1.0 security review (partly
#157).
**Verification**: `make check` green; `make build` then grep both `dist/chrome`
and `dist/firefox` bundles to prove the test phrase is absent from a release
build, and `make build-debug` + the same grep to prove it is present when the
flag is set. Results reported in the PR body.
Out of scope: `script/lint` being prettier-only (#152), and any other DEBUG
consumers' behavior.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Problem
src/shared/constants.js:1isconst DEBUG = true;onmain. Combined withsrc/shared/wallet.js:7-13:…every wallet created with the die button in a build made from
mainreceivesthe hardcoded phrase
cube evolve unfold result inch risk jealous skill hotel bulb night wreck(constants.js:2-3), which is committed in this public repo.Any funds sent to such a wallet are immediately drainable by anyone.
There is currently no way to produce a non-debug build:
build.js:50-57definesonly the
__BUILD_*__constants and nothing flipsDEBUG. The real entropypath (
wallet.js:9-11) is therefore dead code in every artifact we can buildtoday.
Secondary consequences of
DEBUG === true:src/shared/log.js:19-21 isDebug()keeps the red "DEBUG / INSECURE" banner permanently on and leaves
debugFetchrequest/response logging always active (log.js:46-53).This is the single highest-severity item in the repo and blocks 1.0.0.
Implementation requirements
DEBUGa build-time constant that defaults to off. Follow theexisting pattern in
build.js:50-57: add a__BUILD_DEBUG__definealongside the current
__BUILD_*__defines, and havesrc/shared/constants.jsread it.projects should be configured with environment variables"). Suggested:
AUTISTMASK_DEBUG=1 make buildturns it on; a baremake buildproduces arelease build with
DEBUG === false.Policy and
RULES.md:76-80, it must still enable exactly the red banner plusthe hardcoded test phrase, and nothing else. Do not add new
if (DEBUG)branches.
DEBUG_MNEMONICin the tree; it stays reachable only when the debugbuild flag is set.
#145 (
src/popup/views/settings.js:158-178,:339-382) andsrc/shared/log.js. Make sure a release build is coherent: the runtimetoggle must not be able to re-enable the hardcoded-mnemonic path.
make buildvariant or document the env var in the README so the debugbuild remains easy to produce for development.
Definition of done
make buildproducesdist/chromeanddist/firefoxartifacts in which
DEBUGisfalse.generateMnemonic()returns a freshly generated12-word phrase from
Mnemonic.fromEntropy— neverDEBUG_MNEMONIC.AUTISTMASK_DEBUG=1 make build(or the documented equivalent) stillproduces a debug build with the banner and the test phrase.
generateMnemonic()calls withthe debug flag off return different, valid BIP-39 phrases, and that
neither equals
DEBUG_MNEMONIC.README.md.TODO.mdupdated in the same commit.make checkpasses.Manager note — dispatching this now as the first work unit of the 1.0.0 push.
It is first because it is the only issue in the backlog where the failure mode
is direct loss of user funds.
Two extra requirements for the implementer, beyond the issue body:
1. Refresh
TODO.mdproperly in this commit. It is stale in ways this PRshould clear up, not just append to:
feat/issue-144-settings-aboutwith "another agent working as of2026-07-06", and that the untracked
scripts/directory needs resolving.Both are done — that branch landed as #145 on 2026-07-26, and
scripts-to-rule-them-all landed as #148.
make checkonmainat
23aeae4today and it passes. The corresponding Future Step ("Verify mainpasses make check after the feature branch merges") is therefore complete and
should be removed.
filed backlog (#149-#168) rather than the old free-text list. Keep the
"Prune stale branches" step — it is now tracked as #167 — and the pre-1.0
security review step, part of which is now #157.
2. Verification standard for the mnemonic assertion. The DoD asks for a
test that two successive
generateMnemonic()calls differ and that neitherequals
DEBUG_MNEMONIC. Make that test meaningful rather than tautological:assert the returned phrase is a valid BIP-39 phrase via
isValidMnemonic,has the expected word count, and that the debug path still returns
DEBUG_MNEMONICwhen the flag is on. A test that only checksa !== bwould pass against a broken implementation that returns a counter.Context the implementer should know:
make checkis green onmaintoday, soany red you see is yours. Also note
script/lintis currently onlyprettier --checkand cannot catch undefined identifiers (#152) — do not relyon it to tell you a rename is complete; grep.
Implementation plan (branch
fix/issue-149-debug-build-flag, frommainat23aeae4):1.
build.js— readAUTISTMASK_DEBUGfrom the environment and add a__BUILD_DEBUG__entry to the existingdefinemap next to the__BUILD_*__defines:
AUTISTMASK_DEBUG=1(exact match) turns the debug build on; anything else,including unset, empty, or a typo, produces a release build. The insecure
direction requires the explicit opt-in, so a mistyped value fails safe.
DEBUG BUILD - INSECUREvsrelease build) so it is obvious in build output which artifact was made.2.
src/shared/constants.js— replaceconst DEBUG = true;with the sametypeofguard patternsrc/shared/buildInfo.jsalready uses for the otherbuild-time defines, defaulting to
falsewhen the define is absent (jest,direct
require):const DEBUG = typeof __BUILD_DEBUG__ !== "undefined" ? __BUILD_DEBUG__ : false;DEBUG_MNEMONICstays in the tree, exported as today.3. Runtime toggle coherence (the #145 interaction).
generateMnemonic()reads the compile-time
DEBUGbinding directly, notisDebug()fromlog.js.isDebug()isDEBUG || _runtimeDebug, and_runtimeDebugis whatthe settings easter-egg toggle drives — it feeds the banner
(
views/helpers.js:71) and the log threshold only. So in a release build themnemonic path is unreachable no matter what the user toggles at runtime, and I
am keeping it that way rather than routing wallet.js through
isDebug(). Iwill add a comment at the
wallet.jscall site recording that this must neverbecome
isDebug(), and a regression test that callssetRuntimeDebug(true)and asserts
generateMnemonic()still returns fresh entropy. No behavior ofthe toggle itself changes (still banner + log level), so no new
if (DEBUG)branch is introduced and the README DEBUG Mode Policy is respected.
4. Tests — new
tests/wallet.test.js, meeting the verification standard inthe manager comment (not just
a !== b):generateMnemonic()calls differ, both passisValidMnemonic, both are 12 words, and neither equalsDEBUG_MNEMONIC;setRuntimeDebug(true): still fresh, valid, and notDEBUG_MNEMONIC;globalThis.__BUILD_DEBUG__ = trueandjest.resetModules(),DEBUG === trueandgenerateMnemonic()returnsDEBUG_MNEMONIC— so thedebug path is proven to still work rather than silently deleted.
5.
Makefile— add abuild-debugtarget (AUTISTMASK_DEBUG=1+ the samebuild) so the debug build stays a one-liner for development, and document the
env var in the README Getting Started / DEBUG Mode Policy sections.
6.
TODO.md— full refresh in the same commit per the manager comment:Status rewritten (
feat/issue-144-settings-aboutlanded as #145,scripts-to-rule-them-all landed as #148,
make checkgreen onmainat23aeae4), the completed "verify main passes make check" Future Step removed,Next Step set to this issue, Future Steps rewritten against the #149-#168
backlog, keeping branch pruning (#167) and the pre-1.0 security review (partly
#157).
Verification:
make checkgreen;make buildthen grep bothdist/chromeand
dist/firefoxbundles to prove the test phrase is absent from a releasebuild, and
make build-debug+ the same grep to prove it is present when theflag is set. Results reported in the PR body.
Out of scope:
script/lintbeing prettier-only (#152), and any other DEBUGconsumers' behavior.