Skip to content

security: harden self-update against supply-chain and path-traversal attacks#878

Open
Sunil56224972 wants to merge 1 commit into
usestrix:mainfrom
Sunil56224972:pr4-self-update-hardening
Open

security: harden self-update against supply-chain and path-traversal attacks#878
Sunil56224972 wants to merge 1 commit into
usestrix:mainfrom
Sunil56224972:pr4-self-update-hardening

Conversation

@Sunil56224972

Copy link
Copy Markdown

Summary

Three related hardening measures for _download_and_replace() in the self-update mechanism. These address the highest-severity findings from a security audit of the codebase.


1. Refuse unverified binaries — High Severity

Before: When no SHA-256 digest is published for a release asset, the code printed a dim yellow warning and proceeded to replace the running binary with unverified content:
python console.print('[dim yellow]No published checksum available; skipping verification[/]')

Risk: If an attacker compromises the GitHub release (account takeover, Actions supply-chain attack, or CDN MitM on a misconfigured proxy), they can inject a malicious binary that gets installed without any integrity check. The user sees only a dim warning that is easy to miss.

After: raise RuntimeError(...) — the update is aborted. The operator can still install manually after independent verification.


2. Zip-slip path traversal guard (Windows) — High Severity

Before: zf.extract(binary_name, tmp_dir) uses the archive member name directly.

Risk: A crafted zip containing a path like ../../malicious.exe writes outside tmp_dir. Python >=3.12 has partial mitigations, but Python 3.11 (in-support per pyproject.toml requires-python = '>=3.11') is fully vulnerable.

After: Resolve the extraction target path and verify it stays inside tmp_dir before extracting.


3. Tar-slip guard + Python 3.11 compatibility — High/Medium Severity

Before: tf.extract(binary_name, tmp_dir, filter='data')

Risk (tar-slip): Without path validation, tar members with absolute paths or .. components could escape the staging directory.

Risk (compatibility): The filter parameter was introduced in Python 3.12. On Python 3.11 this raises TypeError, causing the entire self-update to crash.

After: Validate the resolved path (same pattern as the zip guard), use filter='data' when available, and fall back gracefully on Python <3.12.


Files changed

  • strix/interface/update_check.py

Testing

  • Verified that the normal update flow (with published checksums) works unchanged
  • Missing checksums now correctly abort with a clear error message
  • Path traversal attempts in both zip and tar archives are detected and rejected
  • Python 3.11 compatibility restored for the tar extraction path

…attacks

Three related hardening measures for _download_and_replace():

1. REFUSE UNVERIFIED BINARIES (was: silent skip)

   When no SHA-256 digest is published for a release asset, the
   previous code printed a dim warning and proceeded to replace the
   running binary with unverified content.  If an attacker compromises
   the GitHub release (account takeover, Actions supply-chain, CDN
   MitM on a misconfigured proxy), they can inject a malicious binary
   that is installed without any integrity check.

   Now: raise RuntimeError so the update is aborted.  The operator can
   still install manually after independent verification.

2. ZIP-SLIP GUARD (Windows path)

   zipfile.extract() uses the archive member name as-is.  A crafted
   zip containing '../../malicious.exe' writes outside the staging
   directory.  Python >=3.12 has partial mitigations, but Python 3.11
   (in-support per pyproject.toml requires-python) is fully vulnerable.

   Now: resolve the extraction target and verify it stays inside
   tmp_dir before extracting.

3. TAR-SLIP GUARD + PYTHON 3.11 FALLBACK (Unix path)

   tarfile.extract(filter='data') was introduced in Python 3.12.
   On Python 3.11 it raises TypeError, causing the self-update to
   crash.  Additionally, without the filter on 3.11, tar members
   with absolute paths or '..' components could escape.

   Now: validate the resolved path (like the zip guard), use
   filter='data' when available, and fall back gracefully on 3.11.
@greptile-apps

greptile-apps Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Hardens standalone binary self-updates by requiring GitHub-provided SHA-256 digests and adding explicit archive extraction path checks, with a compatibility fallback for tar extraction.

Confidence Score: 5/5

The PR appears safe to merge, with no actionable changed-code failures identified.

The selected archive member is constrained to the generated flat binary name, supported Python versions retain tarfile's data filter, checksum failures stop before extraction, and update errors preserve the installed executable.

Important Files Changed

Filename Overview
strix/interface/update_check.py Requires verified release assets and adds zip/tar staging-directory checks without introducing a concrete reachable defect.

Reviews (1): Last reviewed commit: "security: harden self-update against sup..." | Re-trigger Greptile

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