Keep restore writes inside the target directory (closes #154)
restoreFile and verifyRestoredFiles joined the stored path onto the target with no containment check, so a ".." segment or an absolute path escaped the target, and a restored symlink could redirect a later child write anywhere on disk. Since age decryption proves a snapshot is readable but not honest, and restore usually runs as root, a forged snapshot became an arbitrary file write. Both call sites now go through containedRestorePath: it rejects a stored path unless filepath.IsLocal accepts it with the leading separator removed (barring "..", absolute, and empty paths), then Lstats each existing ancestor below the target and refuses to descend through a symlink. The target directory itself may be a symlink, and honest symlinks pointing outside the tree are still written verbatim. Model: opus-4-8
This commit was merged in pull request #176.
This commit is contained in:
@@ -38,6 +38,19 @@ release" is exactly the contradiction
|
||||
recorded with no remote backend are marked uploaded so this invariant
|
||||
holds uniformly.
|
||||
|
||||
- 2026-09-22: Made restore refuse any snapshot path that would write
|
||||
outside the target directory
|
||||
([issue #154](https://git.eeqj.de/sneak/vaultik/issues/154)).
|
||||
`restoreFile` and `verifyRestoredFiles` joined the stored path onto the
|
||||
target with no containment check, so a `..` segment or an absolute path
|
||||
escaped the target and a restored symlink could redirect a later child
|
||||
write anywhere on disk. Every stored path is now rejected unless
|
||||
`filepath.IsLocal` accepts it with the leading separator removed, and
|
||||
each existing ancestor directory below the target is `Lstat`ed to refuse
|
||||
descending through a symlink; honest symlinks pointing outside the tree
|
||||
are still written verbatim. age decryption proves a snapshot is
|
||||
readable, not honest, and restore usually runs as root.
|
||||
|
||||
- 2026-09-21: Stopped `--json` from silencing stderr diagnostics
|
||||
([issue #112](https://git.eeqj.de/sneak/vaultik/issues/112)). `--json`
|
||||
used to be folded into `Quiet`, which pinned the log level to `WARN`,
|
||||
|
||||
Reference in New Issue
Block a user