Repository navigation
Conversation
nazbert
added a commit
to nazbert/Deckard
that referenced
this pull request
Jul 12, 2026
…talls
plugin_id/icon_id/wallpaper_id come from a remote manifest.json and were
joined as path components with no validation -- an id like "../../.."
walked shutil.rmtree/install targets out of the app's data dirs
(install_plugin's directory reset, uninstall_icon/-wallpaper/-sd_plus's
rmtree), and an absolute id replaced the base dir entirely. Icon and
wallpaper packs are data-only: a hostile pack got filesystem-wide delete
with no code execution involved.
StoreBackend.is_safe_asset_id now whitelists ids (^[A-Za-z0-9]
[A-Za-z0-9._-]{0,127}$) at every id->path join site, REJECTING on
mismatch (400) rather than normalizing -- a traversal id is a hostile or
broken manifest, not something to quietly repair. The read-only
get_local_sha probes in prepare_* go through the same guard
(get_local_sha_for_id) so an evil catalog entry can't even probe the
filesystem, and a manifest without an id no longer TypeErrors the join.
The __install__.py / requirements.txt runners also ran through
subprocess.run(f"{sys.executable} {path}", shell=True), which broke on
spaces in the data path and allowed shell injection via crafted path
components; both now run as argv lists without a shell.
Marked breaking (!) because install/uninstall of assets whose manifest id
fails the whitelist is now refused instead of acted on.
Covered by tests/scenario_store_id_sanitizer.py (network-free).
Closes StreamController#27
nazbert
added a commit
to nazbert/Deckard
that referenced
this pull request
Jul 12, 2026
…a; zip-slip guard Review round 1 follow-up to the StreamController#27 hardening: close the shell-injection sibling the id/pip de-shelling left behind, and add belt-and-suspenders archive validation. clone_repo (the --devel, non-flatpak install path) ran the remote store catalog's `commit_sha` and `branch` through os.system() f-strings: os.system(f"cd '{local_path}' && git switch {branch_name}") `branch` is plugin["branch"] straight from the catalog with no validation, so a catalog entry `branch: "main; <cmd>"` injected a shell -- the exact class the id/pip runners were de-shelled to prevent. All three os.system git calls (pull / reset --hard / switch) now run as argv lists via `git -C <dir> ...` with no shell. The remote-sourced values are also validated defensively before use: `is_safe_ref_name` rejects shell metachars / whitespace / newlines / leading '-' (git-option smuggling), and `is_safe_commit_sha` enforces the 40-hex form; a bad value returns 400 before any git runs. Also adds `zip_has_unsafe_members` as defense-in-depth before shutil.unpack_archive: GitHub .zip archives are trusted and CPython's zipfile already strips `..`/absolute members, but an explicit check means a future archive-source or format change (tar, which CPython does NOT sanitize identically) can't silently reintroduce a Zip-Slip write. Marked `!` for consistency with the StreamController#27 commit: a catalog whose branch/sha does not conform is now refused rather than executed. Tests (scenario_store_id_sanitizer): ref/sha validator cases; clone_repo refuses an injected branch/sha (400, no git call, injected side-effect marker never created) and only ever invokes git as an argv list (os_sys must not be reached); zip_has_unsafe_members flags traversal + absolute members and passes a clean archive. Red-tested: reverting to os.system trips the shell-use guard; neutering the zip guard fails the slip test.
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.
1.4.9-beta