github tis24dev/proxsave v0.16.0

10 hours ago

ProxSave v0.16.0

🛡️ Restore integrity enforcement, symlink/path hardening, and bounded IO for safer recovery

This release significantly strengthens restore/decrypt safety and integrity. It hardens decision-making against untrusted metadata, enforces checksum verification before any restore/decrypt proceeds, and closes multiple symlink and path-validation bypasses (including staged apply overlays). It also bounds filesystem and input timeout wrappers to prevent goroutine buildup, improves PBS override handling and output key disambiguation, and delivers major test coverage expansion (including ~99% coverage for network rollback/apply logic).

  • Restore integrity: checksum verification is now mandatory

    • Enforced staged backup archive checksum verification before any restore/decrypt begins.
    • Added strict SHA256 parsing/normalization and enforced agreement between manifest and sidecar checksum sources.
    • Rejected raw backup candidates without a verifiable integrity source.
    • Centralized shared prepare-path verification for bundle and raw inputs, preserving both source-artifact checksum and prepared-archive checksum distinctly.
    • Validated and normalized raw backup checksums during discovery (local + rclone), rejecting malformed/conflicting checksums up front.
    • Bounded checksum sidecar reads (local + rclone) with streaming caps and clear errors for oversized/empty checksum files.
    • Rclone checksum probing now uses its own fresh timeout budget (matches documented per-command timeout behavior).
    • Surfaced decompressor Close() errors during restore archive inspection (archives are no longer silently accepted if Close fails).
  • Restore planning hardening: trust archive-backed facts, not spoofable metadata

    • Derived restore compatibility, cluster gating, and hostname warnings from archive-backed facts instead of candidate manifest metadata.
    • Added restore archive analysis of internal backup metadata with category-based fallback paths.
    • When analysis fails in UI workflows, now validate compatibility first before falling back to full restore (compat warnings still shown).
  • Symlink + path security: close escape/bypass classes across restore and staged apply

    • Replaced restore path safety checks with a shared FS-aware resolver that walks components using Lstat/Readlink:
      • Rejects intermediate symlink escapes, loops, and symlinked restore roots.
      • Distinguishes security violations from operational failures so in-root permission/ENOTDIR errors surface normally.
    • Preserved staged network symlinks by using Lstat (no dereference copy), rejected symlinked staged network directories, and extended FS abstraction with Lstat.
    • Validated staged network symlink targets before recreating them:
      • Rewrote safe absolute targets into relative links.
      • Rejected absolute/relative targets that escape the allowed subtree.
    • Applied the same symlink-target validation to firewall/SDN staged sync (syncDirExact), with safe rewrites and escape rejection.
    • Fixed overlay symlink rewriting when destination parents are symlinks (rewrite relative to resolved parent, not lexical parent).
    • Added post-creation overlay symlink revalidation (read back created link, ensure effective target stays within restore root; remove on failure).
    • Safety restore symlink handling now fails on operational validation errors (still warns/skips only for true root-escape targets).
  • Resource safety and robustness: bounded IO/timeouts and race fixes

    • Prevented unbounded goroutine accumulation in timed filesystem wrappers by limiting in-flight safefs operations.
    • Normalized safefs deadline handling so deadline expiry maps consistently to TimeoutError/ErrTimeout (while preserving context.Canceled semantics).
    • Improved safefs timeout test cleanup to avoid leaks and races (local capture of limiter/hooks, drain blocked workers safely).
    • Input package now reuses a single in-flight read per reader/FD, preserves completed results across retries until consumed, and avoids holding the state mutex across blocking waits (with extensive deterministic regression tests).
  • Backup output safety: sanitize path segments to prevent traversal/collisions

    • Introduced path-safe keys for PBS datastore names and PVE storage names when building collector output paths.
    • Prevented path traversal and filename collisions from raw config values while keeping raw names unchanged in metadata and command invocations.
  • PBS datastore overrides: safer semantics and collision-proof output keys

    • Separated override scan roots from real datastore identities with explicit metadata (source, CLI identity, output key).
    • Derived stable path-based output keys for PBS_DATASTORE_PATH overrides while preserving existing names for real CLI-discovered datastores.
    • Guaranteed stable unique datastore output keys across CLI + overrides (fixes real collisions, keeps inventory aligned with written files).
    • Always applied absolute-path overrides even when proxmox-backup-manager is missing/failing/invalid (except ctx cancellation).
    • Rejected relative PBS_DATASTORE_PATH overrides (warn + skip).
    • Improved inventory merge precedence so runtime CLI paths override datastore.cfg for the same identity.
    • Kept override-only entries out of datastore.cfg fallback restore for safety; added broad regression coverage (basename collisions, status filename collisions, restore safety).
  • Network and restore UX/test reliability

    • Added extensive network_apply tests (rollback arm/disarm, NIC repair CLI overrides/conflicts, snapshot IP parsing, command selection, and error paths), bringing coverage to ~99% with no production behavior changes.
    • Improved PVE datastore skip logging:
      • Disabled storages logged as SKIP, offline storages as actionable WARNING, and always emit DEBUG skip details with runtime flags and explicit reason.
      • Fixed detected-datastores report header and extended runtime flag parsing tests.
  • Compatibility and correctness fixes

    • Compatibility parser now recognizes full Proxmox names like “Proxmox VE”, “Proxmox Backup”, and “Proxmox Backup Server” (plus existing acronym/hyphenated forms), with regression tests.
    • Trimmed and normalized whitespace-padded manifest EncryptionMode (“ age ” now correctly triggers decryption).
    • Validated prepared archive paths against encryption mode and suffix:
      • Rejects inconsistent mode/suffix combinations and prevents identical input/output paths by generating unique output names when needed.
  • CI, build, and maintenance

    • Updated GitHub Actions (goreleaser-action v7, attest-build-provenance v4).
    • Updated go.mod and ensured Makefile coverage targets honor the go.mod toolchain via GOTOOLCHAIN.
    • Webhook Discord content fallback was introduced and then reverted (no net behavior change).

Overall: materially safer restores and decrypts (integrity required, spoof-resistant decisions), hardened symlink/path handling across restore and staged apply, bounded IO/input wrappers to prevent resource buildup, and improved PBS override safety and observability with strong regression coverage.

Changelog

Don't miss a new proxsave release

NewReleases is sending notifications on new releases.