File ownership is never recorded, so a restore as root makes every file root:root #216

Closed
opened 2026-10-06 01:49:41 +02:00 by clawbot · 1 comment
Collaborator

The scanner reads uid and gid by asserting info.Sys() to an interface with Uid() and Gid() methods (internal/snapshot/scanner.go:1107-1112, :1131-1136, :1170-1178). The value is a *syscall.Stat_t, which has Uid and Gid fields but no such methods. The assertion therefore always fails, and uid and gid stay 0. Measured on next at 0700901: a backup taken as uid 1000 stored uid=0 gid=0 for a file, a directory and a symlink.

Trigger: any backup, then a restore as root. internal/vaultik/restore.go:1028-1034 chowns every file and directory to the recorded 0:0. A restore as a normal user prints advice to re-run it as root to preserve the original UID/GID, and following that advice does not help.

The README (:367, :572-574) says uid and gid are recorded and restored.

Definition of done

  1. The scanner records the real uid and gid of files, directories and symlinks on Linux and macOS, read through *syscall.Stat_t.
  2. A test backs up a real file as the current user and asserts that the recorded uid and gid equal os.Getuid() and os.Getgid().
  3. make check passes.

Model: fable-5-1 (audit); opus-5-5 (issue)

The scanner reads uid and gid by asserting `info.Sys()` to an interface with `Uid()` and `Gid()` methods (`internal/snapshot/scanner.go:1107-1112`, `:1131-1136`, `:1170-1178`). The value is a `*syscall.Stat_t`, which has `Uid` and `Gid` fields but no such methods. The assertion therefore always fails, and uid and gid stay 0. Measured on `next` at `0700901`: a backup taken as uid 1000 stored `uid=0 gid=0` for a file, a directory and a symlink. Trigger: any backup, then a restore as root. `internal/vaultik/restore.go:1028-1034` chowns every file and directory to the recorded `0:0`. A restore as a normal user prints advice to re-run it as root to preserve the original UID/GID, and following that advice does not help. The README (`:367`, `:572-574`) says uid and gid are recorded and restored. ## Definition of done 1. The scanner records the real uid and gid of files, directories and symlinks on Linux and macOS, read through `*syscall.Stat_t`. 2. A test backs up a real file as the current user and asserts that the recorded uid and gid equal `os.Getuid()` and `os.Getgid()`. 3. `make check` passes. Model: fable-5-1 (audit); opus-5-5 (issue)
clawbot self-assigned this 2026-10-06 01:49:41 +02:00
Author
Collaborator

Fixed in #241: the scanner now reads the Uid and Gid fields of *syscall.Stat_t for files, directories and symlinks, and a test backs up real files on disk and checks the recorded uid and gid against os.Getuid() and os.Getgid(). The test can only catch the defect on a non-root run, since the Docker build runs tests as root.

Model: opus-5-5

Fixed in https://git.eeqj.de/sneak/vaultik/pulls/241: the scanner now reads the `Uid` and `Gid` fields of `*syscall.Stat_t` for files, directories and symlinks, and a test backs up real files on disk and checks the recorded uid and gid against `os.Getuid()` and `os.Getgid()`. The test can only catch the defect on a non-root run, since the Docker build runs tests as root. Model: opus-5-5
Sign in to join this conversation.