2026-07-22 - 2026-10-22
Overview
4 Releases published by 1 user
Published
v1.0.0-rc4
Published
v1.0.0-rc3
Published
v1.0.0-rc2
Published
v1.0.0-rc1
81 Pull requests merged by 1 user
Merged
#196 Point the commandWait comment at the Dockerfile's test limit (closes #195)
Merged
#193 Keep Go's build cache in check builds: re-vendor sneak/prompts e3f79c4 (closes #129)
Merged
#194 Set the time zone in main and run Entry in its own test process (closes #192)
Merged
#191 Log the audit fixes in TODO.md
Merged
#190 A secret mv between vaults unlocks both vaults before taking the lock
Merged
#188 Ask for the mnemonic and passphrase before taking the state directory lock
Merged
#185 A cross-vault secret mv that cannot remove the source fails (closes #159)
Merged
#162 Hold the encrypt and decrypt result in memory until it is written (closes #143)
Merged
#182 Commands fail when currentvault names no vault (closes #156)
Merged
#187 Print every time in UTC, whatever the time zone
Merged
#186 Unknown subcommands of vault, unlocker, version and generate fail
Merged
#175 Ask for the new passphrase in unlocker add when the variable is set (closes #154)
Merged
#172 Stop vault creation when a vault's metadata cannot be read
Merged
#184 README says secret add drops one trailing newline and import keeps it
Merged
#179 Include gpg's stderr in the error when gpg fails
Merged
#181 secret version list no longer shows a version without NOT_AFTER as expired (closes #150)
Merged
#178 Print an empty unlocker or vault list as [] in JSON
Merged
#170 A secret too large for the locked-memory limit fails with an error, not a panic
Merged
#176 Count every file of each version in secret info's Total Size
Merged
#174 Remove secret vault import
Merged
#180 version promote --help says the current file is rewritten (closes #153)
Merged
#177 Refuse an existing vault before asking for the mnemonic
Merged
#166 secret get fails when it cannot write the value
Merged
#168 secret list gives each secret's own creation and last-update times (closes #142)
Merged
#167 Use gpg.conf's default-key when unlocker add pgp has no --keyid
Merged
#171 A wrong passphrase gives an error that says so
Merged
#165 Ask for the passphrase on the controlling terminal, not stdin
Merged
#164 Print the mnemonic and the vault and unlocker listings to stdout
Merged
#163 Make another unlocker current when the current one is removed
Merged
#161 A failed secret add --force leaves the secret unchanged
Merged
#160 Derive the vault key from the mnemonic's words however they are spaced (closes #135)
Merged
#134 Remove the keychain and Secure Enclave unlockers (closes #132)
Merged
#130 Copy go-bip39 into internal/bip39 (closes #122)
Merged
#128 Re-vendor the canonical files from sneak/prompts at dd4027b (closes #121)
Merged
#53 Make script/test fail on flaky failures and enable -race (closes #32)
Merged
#125 Keep Go's build cache between builds (closes #124)
Merged
#127 Stop the terminal tests reading a pty nobody opened (closes #126)
Merged
#123 Make the tests fast under the race detector (closes #120)
Merged
#119 Test only small secrets in the size tests (closes #52)
Merged
#118 Rename the Go module to sneak.berlin/go/secret (closes #43)
Merged
#117 Format and check markdown with prettier in make fmt and fmt-check (closes #110)
Merged
#116 Name only the mnemonic when it cannot be read (closes #115)
Merged
#114 Give each failure one error value (closes #113)
Merged
#112 Check errors by identity, not by message text, in tests (closes #49)
Merged
#111 Say the mnemonic still opens a vault its unlocker cannot (closes #47)
Merged
#109 Make an unlocker's ID the name of its directory (closes #98)
Merged
#107 Make the README's storage and file format text match the code (closes #102)
Merged
#108 Create a vault whole in a temporary directory, then select it (closes #105)
Merged
#106 Delete the keychain item or Secure Enclave key of a failed unlocker add (closes #89)
Merged
#101 Delete .tmp- leftovers of a killed command when the lock is next taken (closes #75)
Merged
#103 Add the README's required sections and clear stale TODO.md items (closes #46)
Merged
#104 Put age identity keys into locked buffers through one function (closes #38)
Merged
#96 Type-check and lint the macOS build from Linux (closes #50)
Merged
#100 Ask before removing a secret, version, vault or unlocker (closes #39)
Merged
#99 Give every new unlocker a directory of its own (closes #71)
Merged
#94 Read secret environment variables once per command, then unset them (closes #60)
Merged
#97 Use the canonical golangci-lint config (closes #66)
Merged
#95 Make secret unlocker add pgp work on Linux (closes #88)
Merged
#93 Check vault names in every command that takes one (closes #68)
Merged
#92 Run the checks again on every script/cibuild (closes #54)
Merged
#90 Leave no partial unlocker directory when adding an unlocker fails (closes #48)
Merged
#91 Skip corrupt unlocker metadata in unlocker select and remove (closes #72)
Merged
#86 Print usage only for a command called wrongly (closes #41)
Merged
#87 Keep secret get values in locked memory (closes #37)
Merged
#84 Build with the local docker daemon; add script/build (closes #44)
Merged
#64 Stop vault safety checks from reading unreadable state as empty (closes #51)
Merged
#85 Ignore secrets and editor files in .gitignore (closes #40)
Merged
#82 Refuse to create a vault that already exists (closes #74)
Merged
#83 Speed up the internal/cli lock and two-vault tests (closes #80)
Merged
#81 Reject secret mv onto the same secret under another name (closes #78)
Merged
#79 Run golangci-lint only in docker, on every run (closes #55)
Merged
#61 Keep unlocker list working when unlocker metadata is corrupt (closes #42)
Merged
#76 Stop secret mv deleting a secret moved onto itself (closes #73)
Merged
#69 Lock the state directory and write vault files atomically (closes #34)
Merged
#77 Accept a version argument only if the secret has that version (closes #67)
Merged
#62 Wipe memguard buffers on every exit and restore echo (closes #35)
Merged
#65 Reject invalid secret names before any command builds a path (closes #33)
Merged
#63 Keep the keychain unlocker passphrase in locked memory (closes #36)
Merged
#58 Let a plain docker build pass and stamp the git version (closes #57)
Merged
#29 Update golangci-lint to v2.12.2 with canonical config
Merged
#28 Add .editorconfig (closes #27)
1 Pull request proposed by 1 user
Proposed
#59 next → main: a plain docker build passes and stamps the version
86 Issues closed from 1 user
Closed
#195 The commandWait comment names a 30-second test limit that no longer exists
Closed
#192 make test sometimes fails with a data race on time.Local in cli.Entry
Closed
#173 Log the audit fixes in TODO.md in one change
Closed
#189 A secret mv between vaults asks for the passphrase while holding the state directory lock
Closed
#152 Commands that prompt for a mnemonic or passphrase hold the state directory lock while waiting, so other changing commands wait silently
Closed
#159 A cross-vault secret mv whose source could not be removed reports "Moved" and exits 0, leaving the secret in both vaults
Closed
#143 secret decrypt and secret encrypt truncate the --output file before they can fail, and --input equal to --output destroys the input
Closed
#156 A currentvault file naming a vault that does not exist makes secret list report an empty vault with exit 0
Closed
#169 Listed times are in the local time zone, not UTC as AGENTS.md requires
Closed
#183 An unknown subcommand of vault, unlocker, version or generate prints help and exits 0
Closed
#154 With SB_UNLOCK_PASSPHRASE set, secret unlocker add passphrase gives the new unlocker the old passphrase without asking
Closed
#140 A vault with corrupt or unreadable metadata is skipped when choosing the next derivation index, so the next vault gets its key
Closed
#158 README does not say that secret add drops one trailing newline from the value while secret import keeps it
Closed
#146 A gpg failure is reported as only its exit status; gpg's reason on stderr is dropped
Closed
#150 secret version list shows STATUS expired for every version that is not current, including ones with no NOT_AFTER
Closed
#148 secret unlocker list --json prints "unlockers": null when the vault has no unlockers
Closed
#145 A secret larger than about half the locked-memory limit crashes secret add, import and generate secret with a panic
Closed
#147 secret info counts only metadata.age, so Total Size leaves out every secret value
Closed
#139 secret vault import cannot succeed on any vault the tool creates, and the mnemonic help points at secret import
Closed
#153 secret version promote --help says it updates the current symlink; current is a plain file
Closed
#151 secret init and secret vault create ask for the mnemonic and passphrase before refusing a vault that already exists
Closed
#155 secret get ignores a failed write of the value to stdout and exits 0
Closed
#142 secret list reports the time of the listing as every secret's creation and last-update time
Closed
#141 secret unlocker add pgp without --keyid fails when gpg.conf sets a default-key, because gpgconf prefixes the value with a quote
Closed
#157 A wrong passphrase is reported as "no identity matched any of the recipients" with advice to make a new unlocker from the mnemonic
Closed
#144 The passphrase prompt reads stdin, so secret add --force with a piped value and secret encrypt/decrypt from stdin cannot ask for the passphrase
Closed
#138 secret generate mnemonic, secret vault list and secret unlocker list print their output to stderr, so it cannot be piped or captured
Closed
#137 Removing the current unlocker leaves the vault unable to open through its remaining unlocker
Closed
#136 A secret add --force that fails to unlock the vault still leaves a new version behind
Closed
#135 A mnemonic typed with extra whitespace derives a different long-term key, so the vault cannot be recovered with the same words
Closed
#132 Take the keychain and Secure Enclave unlockers out of the build and the release
Closed
#149 A secret add --force that fails to unlock the vault still stores the new value as a stray version
Closed
#133 Keep the macOS research code out of the build and the release
Closed
#122 go-bip39 no longer exists upstream: copy it into the repo, as keyfunc does?
Closed
#121 Re-vendor the canonical files from sneak/prompts at dd4027b
Closed
#32 script/test silently passes on flaky failures, and runs without -race or -timeout
Closed
#124 Compile once, outside the timed test step, so make test with -race fits the 60-second cap
Closed
#126 TestRemoveIgnoresTerminalOnStdout can hang until Go's 10-minute test timeout
Closed
#120 make test with -race takes about 214 s; it must fit the 60-second cap
Closed
#52 Test suite cannot meet the 20s policy budget once -race is enabled: internal/cli 100MB boundary tests
Closed
#43 Go module path is git.eeqj.de/sneak/secret, policy requires sneak.berlin/go/secret
Closed
#110 make fmt and make fmt-check ignore markdown
Closed
#115 Reading the mnemonic without a terminal says "failed to read passphrase"
Closed
#113 One error value per failure: internal/cli duplicates vault errors, some failures have none, two bip85 errors are unreachable
Closed
#49 Tests assert on error message fragments, never on sentinel identity — error-handling regressions pass silently
Closed
#47 Error messages leak internals and offer no recovery path for corrupted key files
Closed
#98 Two keychain or Secure Enclave unlockers added in the same minute share an ID
Closed
#102 README calls the current-version and current-vault files symlinks and version metadata unencrypted
Closed
#105 init or vault create killed mid-way leaves a vault with no unlocker that cannot be created again
Closed
#89 A failed keychain or Secure Enclave unlocker add leaves its keychain item or Secure Enclave key behind
Closed
#70 vault create on an existing vault re-keys it, making every secret in it undecryptable
Closed
#75 Interrupted commands leave debris: .tmp- leftovers, a vault with no unlocker, an unremovable partial unlocker
Closed
#46 README missing four required sections; TODO.md is stale and describes completed work as pending
Closed
#38 age identity .String() creates unprotected copies of private keys at six call sites
Closed
#50 Darwin-only code is never compiled, linted, or tested by CI, including both hardware-backed unlockers
Closed
#39 No confirmation prompt on any destructive operation
Closed
#71 Replacing an unlocker is not atomic: a crash part-way leaves it unable to open the vault
Closed
#60 Pass the mnemonic in memory instead of the environment, and unset secret environment variables after reading
Closed
#66 golangci-lint warns that the gomodguard linter is deprecated
Closed
#88 secret unlocker add pgp always fails on Linux: it gets the long-term key from the keychain stub
Closed
#68 Vault names accept . and ..; vault import and the vault part of a cross-vault move skip the vault name check
Closed
#54 script/cibuild can report a cached green: docker build serves RUN make check layers from cache
Closed
#48 CreatePGPUnlocker leaves a partial unlocker directory on disk when fingerprint resolution fails
Closed
#72 secret unlocker select and unlocker remove fail when another unlocker's metadata is corrupt
Closed
#41 Cobra prints full usage on internal failures, burying the actual error
Closed
#37 GetSecretVersion copies decrypted secrets out of locked memory into plain []byte
Closed
#44 Makefile hardcodes a personal remote DOCKER_HOST, breaking make docker for everyone else
Closed
#51 checkUnlockerExists fails open: an unenumerable unlockers.d reports "no duplicate" and permits a duplicate unlocker
Closed
#40 .gitignore does not exclude secrets, and .dockerignore does not exclude .git
Closed
#74 Running secret init again over an existing vault makes its secrets undecryptable
Closed
#80 internal/cli tests roughly doubled in run time with the locking change
Closed
#78 On a case-insensitive filesystem, secret mv --force Foo foo deletes the secret
Closed
#55 Run all linting in Docker via Dockerfile.lint + script/lint
Closed
#42 PGPUnlocker.GetID panics on corrupt metadata, and setMnemonicEnv re-exports the mnemonic
Closed
#73 secret mv --force onto the same secret deletes it
Closed
#34 No file locking and no atomic writes: concurrent or interrupted operations corrupt the vault
Closed
#67 secret version rm x ../../.. deletes the vault and beyond: the version argument goes into a path unchecked
Closed
#35 memguard lifecycle is not wired up: Ctrl-C and error exits leave key material in locked memory unwiped
Closed
#33 Critical: secret rm .. deletes the entire vault; rm/mv/import skip name validation
Closed
#36 KeychainData holds the age key passphrase as a plain string through JSON marshalling
Closed
#57 docker build . fails at make test (10 MB secret exceeds the build container's locked-memory limit)
Closed
#56 Run every build, test and lint step in the Dockerfiles at nice -n 19
Closed
#45 script/bootstrap installs golangci-lint unpinned, so local lint diverges from CI
Closed
#30 Adopt canonical .golangci.yml and golangci-lint v2.12.2
Closed
#31 Decision needed: three commits on main carry vendor advertising trailers
Closed
#27 Add .editorconfig
88 Issues created by 1 user
Opened
#27 Add .editorconfig
Opened
#30 Adopt canonical .golangci.yml and golangci-lint v2.12.2
Opened
#31 Decision needed: three commits on main carry vendor advertising trailers
Opened
#32 script/test silently passes on flaky failures, and runs without -race or -timeout
Opened
#33 Critical: secret rm .. deletes the entire vault; rm/mv/import skip name validation
Opened
#34 No file locking and no atomic writes: concurrent or interrupted operations corrupt the vault
Opened
#35 memguard lifecycle is not wired up: Ctrl-C and error exits leave key material in locked memory unwiped
Opened
#36 KeychainData holds the age key passphrase as a plain string through JSON marshalling
Opened
#37 GetSecretVersion copies decrypted secrets out of locked memory into plain []byte
Opened
#38 age identity .String() creates unprotected copies of private keys at six call sites
Opened
#39 No confirmation prompt on any destructive operation
Opened
#40 .gitignore does not exclude secrets, and .dockerignore does not exclude .git
Opened
#41 Cobra prints full usage on internal failures, burying the actual error
Opened
#42 PGPUnlocker.GetID panics on corrupt metadata, and setMnemonicEnv re-exports the mnemonic
Opened
#43 Go module path is git.eeqj.de/sneak/secret, policy requires sneak.berlin/go/secret
Opened
#44 Makefile hardcodes a personal remote DOCKER_HOST, breaking make docker for everyone else
Opened
#45 script/bootstrap installs golangci-lint unpinned, so local lint diverges from CI
Opened
#46 README missing four required sections; TODO.md is stale and describes completed work as pending
Opened
#47 Error messages leak internals and offer no recovery path for corrupted key files
Opened
#48 CreatePGPUnlocker leaves a partial unlocker directory on disk when fingerprint resolution fails
Opened
#49 Tests assert on error message fragments, never on sentinel identity — error-handling regressions pass silently
Opened
#50 Darwin-only code is never compiled, linted, or tested by CI, including both hardware-backed unlockers
Opened
#51 checkUnlockerExists fails open: an unenumerable unlockers.d reports "no duplicate" and permits a duplicate unlocker
Opened
#52 Test suite cannot meet the 20s policy budget once -race is enabled: internal/cli 100MB boundary tests
Opened
#54 script/cibuild can report a cached green: docker build serves RUN make check layers from cache
Opened
#55 Run all linting in Docker via Dockerfile.lint + script/lint
Opened
#56 Run every build, test and lint step in the Dockerfiles at nice -n 19
Opened
#57 docker build . fails at make test (10 MB secret exceeds the build container's locked-memory limit)
Opened
#60 Pass the mnemonic in memory instead of the environment, and unset secret environment variables after reading
Opened
#66 golangci-lint warns that the gomodguard linter is deprecated
Opened
#67 secret version rm x ../../.. deletes the vault and beyond: the version argument goes into a path unchecked
Opened
#68 Vault names accept . and ..; vault import and the vault part of a cross-vault move skip the vault name check
Opened
#70 vault create on an existing vault re-keys it, making every secret in it undecryptable
Opened
#71 Replacing an unlocker is not atomic: a crash part-way leaves it unable to open the vault
Opened
#72 secret unlocker select and unlocker remove fail when another unlocker's metadata is corrupt
Opened
#73 secret mv --force onto the same secret deletes it
Opened
#74 Running secret init again over an existing vault makes its secrets undecryptable
Opened
#75 Interrupted commands leave debris: .tmp- leftovers, a vault with no unlocker, an unremovable partial unlocker
Opened
#78 On a case-insensitive filesystem, secret mv --force Foo foo deletes the secret
Opened
#80 internal/cli tests roughly doubled in run time with the locking change
Opened
#88 secret unlocker add pgp always fails on Linux: it gets the long-term key from the keychain stub
Opened
#89 A failed keychain or Secure Enclave unlocker add leaves its keychain item or Secure Enclave key behind
Opened
#98 Two keychain or Secure Enclave unlockers added in the same minute share an ID
Opened
#102 README calls the current-version and current-vault files symlinks and version metadata unencrypted
Opened
#105 init or vault create killed mid-way leaves a vault with no unlocker that cannot be created again
Opened
#110 make fmt and make fmt-check ignore markdown
Opened
#113 One error value per failure: internal/cli duplicates vault errors, some failures have none, two bip85 errors are unreachable
Opened
#115 Reading the mnemonic without a terminal says "failed to read passphrase"
Opened
#120 make test with -race takes about 214 s; it must fit the 60-second cap
Opened
#121 Re-vendor the canonical files from sneak/prompts at dd4027b
Opened
#122 go-bip39 no longer exists upstream: copy it into the repo, as keyfunc does?
Opened
#124 Compile once, outside the timed test step, so make test with -race fits the 60-second cap
Opened
#126 TestRemoveIgnoresTerminalOnStdout can hang until Go's 10-minute test timeout
Opened
#129 make test takes over 20 seconds: every run compiles everything with -race
Opened
#131 Finish 1.0 and tag it; after that, bugfixes only
Opened
#132 Take the keychain and Secure Enclave unlockers out of the build and the release
Opened
#133 Keep the macOS research code out of the build and the release
Opened
#135 A mnemonic typed with extra whitespace derives a different long-term key, so the vault cannot be recovered with the same words
Opened
#136 A secret add --force that fails to unlock the vault still leaves a new version behind
Opened
#137 Removing the current unlocker leaves the vault unable to open through its remaining unlocker
Opened
#138 secret generate mnemonic, secret vault list and secret unlocker list print their output to stderr, so it cannot be piped or captured
Opened
#139 secret vault import cannot succeed on any vault the tool creates, and the mnemonic help points at secret import
Opened
#140 A vault with corrupt or unreadable metadata is skipped when choosing the next derivation index, so the next vault gets its key
Opened
#141 secret unlocker add pgp without --keyid fails when gpg.conf sets a default-key, because gpgconf prefixes the value with a quote
Opened
#142 secret list reports the time of the listing as every secret's creation and last-update time
Opened
#143 secret decrypt and secret encrypt truncate the --output file before they can fail, and --input equal to --output destroys the input
Opened
#144 The passphrase prompt reads stdin, so secret add --force with a piped value and secret encrypt/decrypt from stdin cannot ask for the passphrase
Opened
#145 A secret larger than about half the locked-memory limit crashes secret add, import and generate secret with a panic
Opened
#146 A gpg failure is reported as only its exit status; gpg's reason on stderr is dropped
Opened
#147 secret info counts only metadata.age, so Total Size leaves out every secret value
Opened
#148 secret unlocker list --json prints "unlockers": null when the vault has no unlockers
Opened
#149 A secret add --force that fails to unlock the vault still stores the new value as a stray version
Opened
#150 secret version list shows STATUS expired for every version that is not current, including ones with no NOT_AFTER
Opened
#151 secret init and secret vault create ask for the mnemonic and passphrase before refusing a vault that already exists
Opened
#152 Commands that prompt for a mnemonic or passphrase hold the state directory lock while waiting, so other changing commands wait silently
Opened
#153 secret version promote --help says it updates the current symlink; current is a plain file
Opened
#154 With SB_UNLOCK_PASSPHRASE set, secret unlocker add passphrase gives the new unlocker the old passphrase without asking
Opened
#155 secret get ignores a failed write of the value to stdout and exits 0
Opened
#156 A currentvault file naming a vault that does not exist makes secret list report an empty vault with exit 0
Opened
#157 A wrong passphrase is reported as "no identity matched any of the recipients" with advice to make a new unlocker from the mnemonic
Opened
#158 README does not say that secret add drops one trailing newline from the value while secret import keeps it
Opened
#159 A cross-vault secret mv whose source could not be removed reports "Moved" and exits 0, leaving the secret in both vaults
Opened
#169 Listed times are in the local time zone, not UTC as AGENTS.md requires
Opened
#173 Log the audit fixes in TODO.md in one change
Opened
#183 An unknown subcommand of vault, unlocker, version or generate prints help and exits 0
Opened
#189 A secret mv between vaults asks for the passphrase while holding the state directory lock
Opened
#192 make test sometimes fails with a data race on time.Local in cli.Entry
Opened
#195 The commandWait comment names a 30-second test limit that no longer exists