Reject invalid secret names before any command builds a path (closes #33)
check / check (push) Successful in 1m13s

`secret rm ..` resolved to the vault directory and deleted the whole
vault; `secret rm .` and `secret rm ""` deleted every secret. rm, mv and
import built paths from the name without checking it, and so did the
version commands, encrypt and decrypt.

vault.ValidateSecretName wraps the existing name rule and returns
ErrInvalidSecretName. Each of those commands calls it on the name as
given, both names for a move, before building any path. AddSecret and
GetSecretVersion use it too, so the rule has one implementation.

The regression test snapshots every file under the state directory of
two in-memory vaults and requires it unchanged after each rejected
command.

Model: opus-5-5
This commit is contained in:
2026-10-03 12:31:35 +00:00
parent d52b4f1240
commit 526a6be17b
6 changed files with 264 additions and 12 deletions
+7 -2
View File
@@ -25,6 +25,12 @@ Bring the repo into policy compliance in one commit:
# Completed Steps
- 2026-10-03: Every command that builds a path from a secret name
checks the name first with `vault.ValidateSecretName` and touches
nothing when it is invalid: `rm`, `mv` (both names, within a vault
and between vaults), `import`, `version list`/`promote`/`rm`,
`encrypt` and `decrypt`. Before, `secret rm ..` deleted the whole
vault and `secret rm .` every secret in it.
- 2026-10-02: A plain `docker build .` builds again: the size tests
skip a case that needs more locked memory than the process can
lock, and run every case under `script/cibuild`. The image stamps the
@@ -96,8 +102,7 @@ Bring the repo into policy compliance in one commit:
buffer.Bytes() to GPGEncryptFunc and EncryptWithPassphrase.
- Race conditions: no file locking in vault/secrets.go:142-176;
non-atomic writes can leave the vault inconsistent.
- Input validation: dots in secret names risk path traversal
(vault/secrets.go:75-99); no maximum secret size (DoS).
- Input validation: no maximum secret size (DoS).
- Timing attacks: bytes.Equal passphrase compare (cli/init.go:
209-216); non-constant-time public key compare (vault.go:95-100).
- High priority: