security: harden self-update against supply-chain and path-traversal attacks#878
Open
Sunil56224972 wants to merge 1 commit into
Open
security: harden self-update against supply-chain and path-traversal attacks#878Sunil56224972 wants to merge 1 commit into
Sunil56224972 wants to merge 1 commit into
Conversation
…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.
Contributor
Greptile SummaryHardens 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/5The 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
Reviews (1): Last reviewed commit: "security: harden self-update against sup..." | Re-trigger Greptile |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.exewrites outsidetmp_dir. Python >=3.12 has partial mitigations, but Python 3.11 (in-support perpyproject.toml requires-python = '>=3.11') is fully vulnerable.After: Resolve the extraction target path and verify it stays inside
tmp_dirbefore 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
filterparameter was introduced in Python 3.12. On Python 3.11 this raisesTypeError, 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.pyTesting