Skip to content

Commit 5d17ed7

Browse files
committed
docs: Define trusted computer boundary
Make the secret-output invariant literal about intentional recovery/export output, define the trusted-computer boundary consistently, and warn that shell command text can be retained even when stdin is safe from argv exposure. Update the shared CLI safety footer and its exact-help regression. Validation: focused help regression; Ruff check/format; strict mypy for the parser; git diff --check. The full generic-HRP module still reaches the pre-existing bip32 test dependency tracked by #3/#6 and fixed by #7. fixes #4
1 parent d07024a commit 5d17ed7

6 files changed

Lines changed: 66 additions & 24 deletions

File tree

‎SECURITY.md‎

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,32 @@
11
# Security
22

3-
codex32 handles wallet recovery material. Use a trusted computer and have the
3+
codex32 handles wallet recovery material. A **trusted computer** is under your
4+
exclusive control, is not known or suspected to be compromised, and runs an
5+
operating system and other software you trust for the operation. For wallet
6+
work, that trusted software includes Python, codex32, the terminal,
7+
`bitcoin-cli`, Bitcoin Core, and their relevant configuration. Wallet encryption,
8+
application permissions, and RPC authentication do not make a compromised
9+
computer trusted. Have the
410
software and recovery plan reviewed before relying on it with funds. For
5-
stronger isolation, use codex32 and the Bitcoin Core signing wallet only on a
6-
computer kept permanently offline.
11+
stronger isolation, keep the trusted computer disconnected from every network
12+
before, while, and after it handles private recovery or signing material.
713

814
A valid checksum detects many copying mistakes. It does not prove that a backup
915
belongs to your wallet. A correction is only a suggestion; compare it with the
1016
physical backup and wallet information kept elsewhere.
1117

1218
Python, your terminal, and your operating system may retain secret text in
1319
memory or scrollback. codex32 does not intentionally save secrets and keeps
14-
them out of command arguments and normal machine output, but it cannot
15-
guarantee that every copy is erased from swap, hibernation data, or crash
16-
dumps. Using Tails and shutting down when finished helps mitigate this Python
17-
limitation.
20+
them out of command arguments, logs, and unrelated output. Commands that create,
21+
recover, derive, correct, or explicitly export recovery material intentionally
22+
display it when that is their purpose. codex32 cannot guarantee that every copy
23+
is erased from swap, hibernation data, or crash dumps. Using Tails and shutting
24+
down when finished helps mitigate this Python limitation.
25+
26+
Run a command first and enter recovery material at its prompt, or redirect its
27+
standard input from a separately protected source. Do not embed recovery text in
28+
shell command text: shell history, terminal logging, wrappers, and process
29+
tooling may retain it even though codex32 never receives it as an argument.
1830

1931
## Report a security problem
2032

‎docs/security/invariants.md‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,12 @@ and evidence.
3131
warning and literal `YES` confirmation for every HRP. The bound includes all
3232
admitted classes ranked equal to or better than the candidate, independently
3333
of execution order.
34-
6. Secrets stay out of arguments, logs, ordinary output, and public transfers.
35-
During wallet setup, codex32 transfers the master xprv only through child stdin.
34+
6. Secrets stay out of command arguments, logs, unrelated output, and public
35+
transfers. Commands whose purpose is to create, recover, derive, correct, or
36+
explicitly export recovery material may intentionally display that material
37+
to the operator. During wallet setup, codex32 transfers the master xprv only
38+
through child stdin. Private descriptors exist only in Python memory and child
39+
stdin.
3640
7. Bitcoin Core chains are discovered before entropy or recovery input. The
3741
operator confirms an eligible descriptor wallet by exact name.
3842
8. Wallet state is revalidated before handing Core the master key. Core must
@@ -41,8 +45,8 @@ and evidence.
4145
and verified on every exit path.
4246
10. External text, Core output, public wallet data, and PSBTs are untrusted.
4347
11. Only Bitcoin Core descriptor wallets sign with codex32-derived keys.
44-
Sensitive operations use only codex32 or Core on malware-free computers
45-
with trusted software.
48+
Sensitive operations use only codex32 or Core on a trusted computer as
49+
defined by the security model.
4650
12. Offline hosts disable every network path, including Ethernet, internet,
4751
Tor, Wi-Fi, Bluetooth, and cellular. Online Core nodes synchronize before
4852
their balances or history are trusted.

‎docs/security/model.md‎

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,21 @@ fingerprints, and wallet history cannot spend funds but remain privacy-sensitive
3131

3232
## Operator assumptions
3333

34+
A **trusted computer** is under the operator's exclusive control, is not known
35+
or suspected to be compromised, and runs an operating system and other software
36+
the operator trusts for the operation. For codex32 wallet work, that trusted
37+
software includes the Python environment, codex32, the terminal, `bitcoin-cli`,
38+
Bitcoin Core, and their relevant configuration. An offline trusted computer
39+
remains disconnected from every network before, while, and after it handles
40+
private recovery or signing material. Wallet encryption, application
41+
permissions, and RPC authentication do not make a compromised computer trusted.
42+
3443
The operator must:
3544

3645
- use only Bitcoin Core descriptor wallets to sign with keys derived from a
3746
codex32 master seed;
38-
- use computers believed malware-free and whose other software is trusted for
39-
all codex32 operations and for wallet initialization and signing with Bitcoin
40-
Core;
47+
- use only trusted computers as defined above for codex32 operations, wallet
48+
initialization, and signing with Bitcoin Core;
4149
- disconnect every computer used for offline codex32 or signing work from all
4250
network paths, including Ethernet, internet, Tor, Wi-Fi, Bluetooth, and
4351
cellular;
@@ -53,6 +61,14 @@ The operator must:
5361
- never put recovery text in command arguments or transfer a master seed,
5462
share, xprv, or private descriptor through QR or a network service.
5563

64+
`create`, `secret`, `share`, `correct`, and `xprv` can intentionally display
65+
secret-bearing recovery material because producing or exporting that material is
66+
their purpose. This is distinct from accidental disclosure: unrelated status,
67+
diagnostic, logging, and wallet-integration output must not reveal secrets.
68+
Prompted input and standard-input redirection keep recovery text out of process
69+
arguments, but the operator must also keep the text out of shell command text;
70+
shell history, terminal logging, wrappers, or process tooling may retain it.
71+
5672
## Security limitations
5773

5874
- Python cannot guarantee zeroization, constant-time execution, locked memory,

‎docs/user/guide.md‎

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,24 @@ codex32 detects and reports the local Bitcoin Core network. You do not need to
8787
change `bitcoin.conf` when using the standard local data directory and RPC
8888
port.
8989

90-
Use a computer you believe is malware-free and whose other software you trust.
91-
Only codex32 and Bitcoin Core should perform recovery, derivation, wallet
92-
initialization, or signing. The QR tools below transport only public
93-
descriptors or PSBTs.
90+
Use a trusted computer: one under your exclusive control, not known or suspected
91+
to be compromised, with its operating system, Python environment, terminal,
92+
codex32, `bitcoin-cli`, Bitcoin Core, and relevant configuration trusted for the
93+
operation. Wallet encryption or RPC authentication does not make a compromised
94+
computer safe. An offline trusted computer stays disconnected from every network
95+
before, while, and after it handles private recovery or signing material. Only
96+
codex32 and Bitcoin Core should perform recovery, derivation, wallet
97+
initialization, or signing. The QR tools below transport only public descriptors
98+
or PSBTs.
9499

95100
Bitcoin Core wallet encryption is strongly recommended. Bitcoin Core owns the
96101
passphrase and its prompts; codex32 never asks for, reads, or forwards it.
97102

98-
Do not type recovery text on the same line as a command. Run the command first,
99-
then enter a master seed or shares on the separate `>` line when prompted.
103+
Do not type recovery text on the same line as a command: shell history, terminal
104+
logging, wrappers, or process tooling may retain the command text. Run the
105+
command first, then enter a master seed or shares on the separate `>` line when
106+
prompted. Standard-input redirection also keeps recovery text out of process
107+
arguments, but protect the redirected source separately.
100108
This keeps a 48-character string grouped in fours within an 80-column terminal.
101109
Later share prompts may show a fixed common header after `>`. Never photograph
102110
recovery text or put it in a website, chat, cloud clipboard, or online QR

‎src/codex32/_cli_parser.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,9 @@ def parser(prog: str = "codex32", *, master_seed: bool = False) -> argparse.Argu
8686
if master_seed
8787
else "Check, correct, recover, and derive shares from codex32 backups."
8888
),
89-
epilog="Never include a secret or share in command arguments.\n"
90-
"Enter it when prompted. Some commands also accept piped input.",
89+
epilog="Never put a secret or share in command arguments or shell command text.\n"
90+
"Enter it when prompted; some commands also accept redirected standard input.\n"
91+
"Protect redirected sources separately: shells, terminals, and wrappers may retain text.",
9192
formatter_class=argparse.RawDescriptionHelpFormatter,
9293
allow_abbrev=False,
9394
)

‎tests/test_generic_hrp.py‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,9 @@ def test_cli_split_and_unknown_neutral_summary() -> None:
125125
" create create or confirm a backup, or split an existing secret\n"
126126
" wallet restore a Bitcoin Core wallet\n"
127127
" xprv export the root extended private key\n\n"
128-
"Never include a secret or share in command arguments.\n"
129-
"Enter it when prompted. Some commands also accept piped input.\n"
128+
"Never put a secret or share in command arguments or shell command text.\n"
129+
"Enter it when prompted; some commands also accept redirected standard input.\n"
130+
"Protect redirected sources separately: shells, terminals, and wrappers may retain text.\n"
130131
)
131132
for command in ("check", "correct", "secret", "share"):
132133
assert command in generic_help and command in ms_help

0 commit comments

Comments
 (0)