Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
# Security

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

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

Python, your terminal, and your operating system may retain secret text in
memory or scrollback. codex32 does not intentionally save secrets and keeps
them out of command arguments and normal machine output, but it cannot
guarantee that every copy is erased from swap, hibernation data, or crash
dumps. Using Tails and shutting down when finished helps mitigate this Python
limitation.
them out of command arguments, logs, and unrelated output. Commands that create,
recover, derive, correct, or explicitly export recovery material intentionally
display it when that is their purpose. codex32 cannot guarantee that every copy
is erased from swap, hibernation data, or crash dumps. Using Tails and shutting
down when finished helps mitigate this Python limitation.

Run a command first and enter recovery material at its prompt, or redirect its
standard input from a separately protected source. Do not embed recovery text in
shell command text: shell history, terminal logging, wrappers, and process
tooling may retain it even though codex32 never receives it as an argument.

## Report a security problem

Expand Down
11 changes: 7 additions & 4 deletions docs/security/invariants.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ and evidence.
warning and literal `YES` confirmation for every HRP. The bound includes all
admitted classes ranked equal to or better than the candidate, independently
of execution order.
6. Secrets stay out of arguments, logs, ordinary output, and public transfers.
Private descriptors exist only in Python memory and child stdin.
6. Secrets stay out of command arguments, logs, unrelated output, and public
transfers. Commands whose purpose is to create, recover, derive, correct, or
explicitly export recovery material may intentionally display that material
to the operator. Private descriptors exist only in Python memory and child
stdin.
7. Bitcoin Core chains are discovered before entropy or recovery input. The
operator confirms an eligible descriptor wallet by exact name.
8. Wallet state is revalidated before import. Every import must succeed and the
Expand All @@ -34,8 +37,8 @@ and evidence.
and verified on every exit path.
10. External text, Core output, public wallet data, and PSBTs are untrusted.
11. Only Bitcoin Core descriptor wallets sign with codex32-derived keys.
Sensitive operations use only codex32 or Core on malware-free computers
with trusted software.
Sensitive operations use only codex32 or Core on a trusted computer as
defined by the security model.
12. Offline hosts disable every network path, including Ethernet, internet,
Tor, Wi-Fi, Bluetooth, and cellular. Online Core nodes synchronize before
their balances or history are trusted.
Expand Down
22 changes: 19 additions & 3 deletions docs/security/model.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,21 @@ fingerprints, and wallet history cannot spend funds but remain privacy-sensitive

## Operator assumptions

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

The operator must:

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

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

## Security limitations

- Python cannot guarantee zeroization, constant-time execution, locked memory,
Expand Down
20 changes: 14 additions & 6 deletions docs/user/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,24 @@ codex32 detects and reports the local Bitcoin Core network. You do not need to
change `bitcoin.conf` when using the standard local data directory and RPC
port.

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

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

Do not type recovery text on the same line as a command. Run the command first,
then enter a master seed or shares on the separate `>` line when prompted.
Do not type recovery text on the same line as a command: shell history, terminal
logging, wrappers, or process tooling may retain the command text. Run the
command first, then enter a master seed or shares on the separate `>` line when
prompted. Standard-input redirection also keeps recovery text out of process
arguments, but protect the redirected source separately.
This keeps a 48-character string grouped in fours within an 80-column terminal.
Later share prompts may show a fixed common header after `>`. Never photograph
recovery text or put it in a website, chat, cloud clipboard, or online QR
Expand Down
5 changes: 3 additions & 2 deletions src/codex32/_cli_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@ def parser(prog: str = "codex32", *, master_seed: bool = False) -> argparse.Argu
if master_seed
else "Check, correct, recover, and derive shares from codex32 backups."
),
epilog="Never include a secret or share in command arguments.\n"
"Enter it when prompted. Some commands also accept piped input.",
epilog="Never put a secret or share in command arguments or shell command text.\n"
"Enter it when prompted; some commands also accept redirected standard input.\n"
"Protect redirected sources separately: shells, terminals, and wrappers may retain text.",

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this renders at 87 columns, the only --help line over 80; the guide assumes an 80-column terminal. The reason clause also describes shell command text more than redirected sources. Maybe: "Protect redirected files; shells and terminals may keep text."

formatter_class=argparse.RawDescriptionHelpFormatter,
allow_abbrev=False,
)
Expand Down
5 changes: 3 additions & 2 deletions tests/test_generic_hrp.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,9 @@ def test_cli_split_and_unknown_neutral_summary() -> None:
" create create or confirm a backup, or split an existing secret\n"
" wallet restore a Bitcoin Core wallet\n"
" xprv export the root extended private key\n\n"
"Never include a secret or share in command arguments.\n"
"Enter it when prompted. Some commands also accept piped input.\n"
"Never put a secret or share in command arguments or shell command text.\n"
"Enter it when prompted; some commands also accept redirected standard input.\n"
"Protect redirected sources separately: shells, terminals, and wrappers may retain text.\n"
)
for command in ("check", "correct", "secret", "share"):
assert command in generic_help and command in ms_help
Expand Down
Loading