Skip to content

fix(controller): block tar path-traversal on extraction (D11)#15

Merged
luisguzman-adfa merged 1 commit into
mainfrom
fix/phase1-security-d11-archive-traversal
Jun 19, 2026
Merged

fix(controller): block tar path-traversal on extraction (D11)#15
luisguzman-adfa merged 1 commit into
mainfrom
fix/phase1-security-d11-archive-traversal

Conversation

@luisguzman-adfa

Copy link
Copy Markdown
Collaborator

Summary

Phase 1 (security hardening). TarExtractor extracted archives with tar -xf -C destDir without validating member names. The Import backup flow accepts an arbitrary file (*/*) and restore extracts it into filesDir/rootfs, so a crafted .tar.gz whose members use ../ or absolute paths could escape the destination and overwrite app files — tech-debt item D11 (path-traversal / "tar slip").

Changes

  • deploy/domain/ArchiveEntry (new, pure JVM): escapesRoot(name) rejects absolute paths and .. segments that climb above the destination root; allows benign ./ and an internal a/../b that stays inside. Unit-tested (ArchiveEntryTest).
  • TarExtractor: pre-lists the archive members (tar -t; gzip decompressed in Java and piped) and fails closed — if any member escapes, it aborts before extracting anything. Runs for every extraction (the D6-verified rootfs install included) as defense in depth.
  • DeployFragment: single-quoted the interpolated paths in the backup-creation sh -c pipe (the "unquoted backup pipe" half of D11).

Design notes (per discussion)

We chose safe-by-default for all extractions (not only the untrusted restore). The guard focuses on the real attack — .. escape and absolute members — mirroring tar's own "strip leading slash, forbid climbing out" model, so it does not false-positive on legitimate relative distro rootfs / backup members.

How to identify it in the build / behaviour

  • A malicious archive (member like ../../evil or /etc/x) now fails the restore (Unsafe archive entry (path traversal): …) instead of writing outside the rootfs.
  • Legitimate install/restore is unchanged. Worth confirming on a real device that a normal rootfs install and a normal backup restore still succeed (members are relative by convention).

Testing

ArchiveEntryTest (pure JVM, runs in the CI testDebugUnitTest gate): allows normal relative entries; blocks ../, absolute, and backslash-normalized traversal. Logic also verified out of band (15 cases).

TarExtractor extracted archives with `tar -xf -C destDir` without validating
member names. The "Import backup" flow accepts an arbitrary file and "restore"
extracts it into filesDir/rootfs, so a crafted .tar.gz using `../` or absolute
member names could escape the destination and overwrite app files (tech-debt
D11 path-traversal).

- domain: new pure ArchiveEntry.escapesRoot(name) — rejects absolute paths and
  `..` segments that climb above the root; allows benign `./` and internal
  `a/../b`. Pure JVM, unit-tested (ArchiveEntryTest).
- TarExtractor: pre-list the archive members (tar -t; gzip decompressed in Java
  and piped) and fail closed before extracting if any member escapes. Runs for
  every extraction (the D6-verified rootfs install included) as defense in depth.
- DeployFragment: single-quote the interpolated paths in the backup-creation
  `sh -c` pipe (the "unquoted backup pipe" half of D11).

Note: legitimate distro rootfs / backup members are relative by convention, so
the guard should not false-positive; worth confirming on a real install/restore.
@luisguzman-adfa luisguzman-adfa force-pushed the fix/phase1-security-d11-archive-traversal branch from cbfb358 to cbfa6c9 Compare June 19, 2026 02:47
@luisguzman-adfa luisguzman-adfa merged commit 1d4cf5b into main Jun 19, 2026
1 check passed
@luisguzman-adfa luisguzman-adfa deleted the fix/phase1-security-d11-archive-traversal branch June 19, 2026 04:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant