Validate tar entries before extraction (#2) #3

Merged
stephen merged 1 commit from feat/2-safe-extraction into main 2026-06-16 23:35:05 +00:00
Owner

What changed
Extraction shelled out to tar -xf with no entry checks, so a malicious or corrupt artifact from shared storage could escape the download path. Every tar header is now validated before a single byte is written, and the whole archive is refused if any entry is unsafe.

  • Reject .. traversal and absolute-path entries.
  • Reject symlinks/hardlinks whose target resolves outside the destination; allow contained ones.
  • Reject special files (devices, fifos, and any non file/dir/link type).
  • Parse GNU long-name/long-link and pax path/linkpath overrides so the validated name is the real one.
  • Decompress to a temp tar first so headers can be walked with random access; a rejected archive leaves the destination untouched.

How it was tested

  • make lint clean (actionlint/yq not installed locally; skipped)
  • make test green
  • new behavior has a test: malicious fixtures (traversal, absolute path, escaping symlink, fifo) are refused; a contained symlink plus regular files still extract

CHANGELOG updated? yes

**What changed** Extraction shelled out to `tar -xf` with no entry checks, so a malicious or corrupt artifact from shared storage could escape the download path. Every tar header is now validated before a single byte is written, and the whole archive is refused if any entry is unsafe. - Reject `..` traversal and absolute-path entries. - Reject symlinks/hardlinks whose target resolves outside the destination; allow contained ones. - Reject special files (devices, fifos, and any non file/dir/link type). - Parse GNU long-name/long-link and pax `path`/`linkpath` overrides so the validated name is the real one. - Decompress to a temp tar first so headers can be walked with random access; a rejected archive leaves the destination untouched. **How it was tested** - [x] `make lint` clean (actionlint/yq not installed locally; skipped) - [x] `make test` green - [x] new behavior has a test: malicious fixtures (traversal, absolute path, escaping symlink, fifo) are refused; a contained symlink plus regular files still extract **CHANGELOG updated?** yes
Validate tar entries before extraction (#2)
All checks were successful
test / unit (pull_request) Successful in 24s
test / e2e (pull_request) Successful in 4s
edb1335852
Artifact archives come from shared storage and may be malicious or
corrupt, but extraction shelled out to `tar -xf` with no entry checks.
That let a crafted archive escape the download path via `..` names,
absolute paths, escaping symlinks/hardlinks, or special files.

Walk every header first and refuse the whole archive unless every entry
resolves inside the destination and is a regular file, directory, or a
link whose target stays contained. Validation runs before any write, so
a rejected archive leaves the destination untouched. Decompression now
lands in a temp tar so headers can be inspected with random access.

Covered by malicious fixture tests (traversal, absolute path, escaping
symlink, fifo) plus a contained-link case that still extracts.
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
rasterstate/download-artifact-action!3
No description provided.