What changed, and why it matters
This change makes the COLDCARD hardware wallet display the user's BIP-39 passphrase on the device's own screen after it is applied. This is a deliberate UX change, not a hidden bug. It could slightly increase the risk that someone physically near the device (or a camera) sees the passphrase, but it only appears after the user has already entered it and only on the local screen. The commit does not introduce a remote or software vulnerability.
Treat as a low-severity UX/privacy change rather than a vulnerability. Users who operate COLDCARD in environments where shoulder-surfing or camera surveillance is a concern should be aware that passphrases are now shown on screen. No patch or emergency action is required; consider documenting the behavior in release notes.
Security signals we found
Sensitive user secret (BIP-39 passphrase) rendered in on-screen UI message
No input validation, encryption, or access-control changes
No remote or USB-exposed behavior changed
Comment about USB pubkey/MitM behavior relocated but not modified
Evidence from the diff
The patch modifies shared/seed.py to append the BIP-39 passphrase value to two on-screen confirmation messages: one shown after set_ephemeral_seed() when a passphrase is present, and one shown in apply_pass_value(). It also moves an existing comment about USB pubkey changes. The passphrase is already in memory as a function argument; the change only adds it to UI strings shown on the device display. No network, storage, or cryptographic code is altered.
Changed components
shared/seed.pyset_ephemeral_seed()apply_pass_value()COLDCARD on-screen display UXInspect captured patch +14 / −6
diff --git a/shared/seed.py b/shared/seed.py
index 1b1426a..537882d 100644
--- a/shared/seed.py
+++ b/shared/seed.py
@@ -554,6 +554,10 @@ async def set_ephemeral_seed(encoded, chain=None, summarize_ux=True, bip39pw='',
applied, err_msg = pa.tmp_secret(encoded, chain=chain, bip39pw=bip39pw)
+ # FYI: Might need to bounce the USB connection, because our pubkey has changed,
+ # altho if they have already picked a shared session key, no need, and
+ # would only affect MitM test, which has already been done.
+
dis.progress_bar_show(1)
if not applied:
@@ -562,7 +566,10 @@ async def set_ephemeral_seed(encoded, chain=None, summarize_ux=True, bip39pw='',
xfp = "[" + xfp2str(settings.get("xfp", 0)) + "]"
if summarize_ux:
- await ux_show_story(title=xfp, msg="New temporary master key is in effect now.")
+ msg = "New temporary master key is in effect now."
+ if bip39pw:
+ msg += "\n\nPassphrase: %s" % bip39pw
+ await ux_show_story(title=xfp, msg=msg)
return applied
@@ -737,6 +744,7 @@ def set_seed_value(words=None, encoded=None, chain=None):
async def calc_bip39_passphrase(pw, bypass_tmp=False):
+ # Returns (new) encoded secret, new xfp, old xfp
from glob import dis, settings
dis.fullscreen("Working...")
@@ -753,14 +761,13 @@ async def calc_bip39_passphrase(pw, bypass_tmp=False):
async def set_bip39_passphrase(pw, bypass_tmp=False, summarize_ux=True):
nv, xfp, parent_xfp = await calc_bip39_passphrase(pw, bypass_tmp=bypass_tmp)
+
ret = await set_ephemeral_seed(nv, summarize_ux=summarize_ux, bip39pw=pw,
origin="BIP-39 Passphrase on [%s]" % xfp2str(parent_xfp))
+
dis.draw_status(bip39=int(bool(pw)), xfp=xfp, tmp=1)
- return ret
- # Might need to bounce the USB connection, because our pubkey has changed,
- # altho if they have already picked a shared session key, no need, and
- # would only affect MitM test, which has already been done.
+ return ret
async def remember_ephemeral_seed():
# Compute current xprv and switch to using that as root secret.
@@ -1394,8 +1401,9 @@ async def apply_pass_value(new_pp):
msg = ('Above is the master key fingerprint of the new wallet'
' created by adding passphrase to %s.'
+ '\n\nPassphrase: %s'
'\n\nPress %s to abort, %s to use the new wallet, (1) to apply'
- ' and save to MicroSD for future.') % (msg, X, OK)
+ ' and save to MicroSD for future.') % (msg, new_pp, X, OK)
ch = await ux_show_story(msg, title="[%s]" % xfp_str, escape='1')
if ch == 'x':
Why this scored 23/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.