security: DEBUG hardcoded on — every generated recovery phrase is the public test phrase #149
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
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.