PR #448 replaced the remote rollback path's external tar -xzf + header pre-scan with an in-process safeExtractBackup (Go archive/tar) that validates each entry's realized path — including symlink/hardlink targets — at write time.
The LOCAL rollback callers still use the older extractBackupArchive (external tar -xzf, no link-target validation):
RollbackFromBackup (internal/reconcile/compose.go:249)
ComposeUpIsolated (internal/reconcile/compose.go:351)
Risk is lower than the remote path — these extract on the bosun host and run docker compose up -f <extracted> locally; they do NOT re-push to a root-owned remote FS. An escape would require busybox tar on the bosun host itself (GNU/bsd tar protects against symlink-through extraction). Pre-existing, not a regression from #448.
Recommendation: migrate both callers to safeExtractBackup for parity, so link-target validation is uniform across local and remote rollback. Surfaced by the security re-review of #448.
PR #448 replaced the remote rollback path's external
tar -xzf+ header pre-scan with an in-processsafeExtractBackup(Go archive/tar) that validates each entry's realized path — including symlink/hardlink targets — at write time.The LOCAL rollback callers still use the older
extractBackupArchive(externaltar -xzf, no link-target validation):RollbackFromBackup(internal/reconcile/compose.go:249)ComposeUpIsolated(internal/reconcile/compose.go:351)Risk is lower than the remote path — these extract on the bosun host and run
docker compose up -f <extracted>locally; they do NOT re-push to a root-owned remote FS. An escape would require busybox tar on the bosun host itself (GNU/bsd tar protects against symlink-through extraction). Pre-existing, not a regression from #448.Recommendation: migrate both callers to
safeExtractBackupfor parity, so link-target validation is uniform across local and remote rollback. Surfaced by the security re-review of #448.