Error messages leak internals and offer no recovery path for corrupted key files #47
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?
From the 1.0 security survey. Lowest-severity of the security-adjacent items, but it is the difference between a recoverable vault and a user who believes their secrets are gone.
Problem
No recovery guidance. Only two places in the codebase suggest a next step:
internal/cli/init.go:145-147("Run 'secret generate mnemonic' ...") andinternal/cli/unlockers.go:486("Run 'secret unlocker add passphrase' to create one."). Every other failure surfaces as a bare wrapped I/O error.A corrupt or missing
priv.age,longterm.age,pub.age,metadata.age, orcurrentproduces messages likefailed to read current version file: ...(internal/secret/version.go:534, and similarly at:211,:239,:295,:333,:413;secret.go:293;passphraseunlocker.go:52;pgpunlocker.go:97). None of them mentions the single most important fact available: the vault is recoverable from the BIP39 mnemonic. A user who hits this sees an I/O error and reasonably concludes the data is lost, whensecret vault importwould restore access.Internal detail in user-facing errors. Raw filesystem paths and Go-level failures are wrapped through to the user throughout —
failed to open file %s: %w(internal/cli/secrets.go:615),keychain item not found: %swith the item name (keychainunlocker.go:543). Severity is genuinely low for a local single-user CLI, since the leaked data is the user's own paths, but the messages are inconsistent in voice and detail level, which makes the important ones harder to spot.The plumbing to fix this already exists:
internal/vault/errors.godefines sentinel errors, and PR #29'serr113refactor extracted many more.Definition of done
secret vault importwith the mnemonic — where that recovery genuinely applies.errors.Is/errors.As. Do not flatten error chains to make messages prettier — the sentinel-based control flow depends on them, and breaking it silently changes which failures callers treat as fatal.internal/secret/debug.go, theGODEBUGflag), so nothing is lost for diagnosis.make checkgreen.TODO.mdupdated in the same commit.Implementation requirements
internal/vault/errors.goalready has one.