Found by the audit for #33 (comment on that issue). Same class of defect, not fixed by #65.
Problem
secret version rm, secret version promote and secret get --version put the version argument into a filesystem path without any check. The "cannot remove the current version" guard does not help, because the argument never equals the current version name. With an existing secret x:
secret version rm x "" or secret version rm x . deletes every version of x, the current one included.
secret version rm x .. deletes the secret x.
secret version rm x ../../.. deletes the whole vault. Each further .. climbs one level: all vaults, the state directory, then (Linux, default state directory) ~/.config and the home directory.
An empty shell variable is enough to trigger the first case. promote with such an argument rewrites the current-version pointer to a path outside the secret; get --version reads outside it.
Definition of done
The version argument of version rm, version promote and get --version is accepted only if it names an existing entry of that secret's versions directory, checked on the argument as typed, before any path is built. No filepath.Clean/prefix check; no second copy of a rule.
rm, promote and get --version with "", ., .., ../../.. and a/b each fail with a clear error and non-zero exit.
Regression tests record every file and directory under the state directory (with contents) before each rejected command and require an unchanged record afterwards, the same way the tests in #65 do; asserting only the error is not enough.
TODO.md updated in the same commit.
Sequencing
After #65 lands (same command files, and its test helper is reused).
Model: opus-5-5
Found by the audit for https://git.eeqj.de/sneak/secret/issues/33 (comment on that issue). Same class of defect, not fixed by https://git.eeqj.de/sneak/secret/pulls/65.
## Problem
`secret version rm`, `secret version promote` and `secret get --version` put the version argument into a filesystem path without any check. The "cannot remove the current version" guard does not help, because the argument never equals the current version name. With an existing secret `x`:
- `secret version rm x ""` or `secret version rm x .` deletes every version of `x`, the current one included.
- `secret version rm x ..` deletes the secret `x`.
- `secret version rm x ../../..` deletes the whole vault. Each further `..` climbs one level: all vaults, the state directory, then (Linux, default state directory) `~/.config` and the home directory.
An empty shell variable is enough to trigger the first case. `promote` with such an argument rewrites the current-version pointer to a path outside the secret; `get --version` reads outside it.
## Definition of done
- The version argument of `version rm`, `version promote` and `get --version` is accepted only if it names an existing entry of that secret's `versions` directory, checked on the argument as typed, before any path is built. No `filepath.Clean`/prefix check; no second copy of a rule.
- `rm`, `promote` and `get --version` with `""`, `.`, `..`, `../../..` and `a/b` each fail with a clear error and non-zero exit.
- Regression tests record every file and directory under the state directory (with contents) before each rejected command and require an unchanged record afterwards, the same way the tests in https://git.eeqj.de/sneak/secret/pulls/65 do; asserting only the error is not enough.
- `TODO.md` updated in the same commit.
## Sequencing
After https://git.eeqj.de/sneak/secret/pulls/65 lands (same command files, and its test helper is reused).
Model: opus-5-5
Labelled critical: secret version rm x ../../.. (or "", ., .. as the version) deletes every version of a secret, the secret, the whole vault, or directories above it, with nothing to stop it.
Model: opus-5-5
Labelled critical: `secret version rm x ../../..` (or `""`, `.`, `..` as the version) deletes every version of a secret, the secret, the whole vault, or directories above it, with nothing to stop it.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Found by the audit for #33 (comment on that issue). Same class of defect, not fixed by #65.
Problem
secret version rm,secret version promoteandsecret get --versionput the version argument into a filesystem path without any check. The "cannot remove the current version" guard does not help, because the argument never equals the current version name. With an existing secretx:secret version rm x ""orsecret version rm x .deletes every version ofx, the current one included.secret version rm x ..deletes the secretx.secret version rm x ../../..deletes the whole vault. Each further..climbs one level: all vaults, the state directory, then (Linux, default state directory)~/.configand the home directory.An empty shell variable is enough to trigger the first case.
promotewith such an argument rewrites the current-version pointer to a path outside the secret;get --versionreads outside it.Definition of done
version rm,version promoteandget --versionis accepted only if it names an existing entry of that secret'sversionsdirectory, checked on the argument as typed, before any path is built. Nofilepath.Clean/prefix check; no second copy of a rule.rm,promoteandget --versionwith"",.,..,../../..anda/beach fail with a clear error and non-zero exit.TODO.mdupdated in the same commit.Sequencing
After #65 lands (same command files, and its test helper is reused).
Model: opus-5-5
Labelled critical:
secret version rm x ../../..(or"",.,..as the version) deletes every version of a secret, the secret, the whole vault, or directories above it, with nothing to stop it.Model: opus-5-5