fix: harden what the security scan flagged (https-only downloads, no strtok, SHA-1 marked not for security) #1470
No reviewers
Labels
No labels
accessibility
autorelease: pending
autorelease: tagged
bug
dependencies
documentation
duplicate
enhancement
github_actions
good first issue
help wanted
invalid
question
testing wanted
wontfix
No milestone
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set
Reference
MagicBeanDev/Hookshot!1470
Loading…
Reference in a new issue
No description provided.
Delete branch "sec-hardening"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Follows up the security-scan triage (the real finding, the Dependabot cooldown, landed in #1464). The rest were false positives; where a small change makes the code actually safer, this makes it:
builder/linux/linux_update.pysends everyurlopenthrough_https(), which refuses anything else (the release API's asset link included).scripts/release_parts.py'sget()does the same, so the CI token is never sent over plain http.strtokin setup.builder/setup/setup.csplits the setup list withnext_line(): strtok's work without its hidden state. Checked on CRLF, blank lines, an empty list, and a list with no last newline.usedforsecurity=False. The digests are the same, so every build cache stays valid. It also lets the scripts run on FIPS-mode Pythons.chmod 0o755now has a note on why: the launcher has to run.The "generic API key" hits are 64-bit shader IDs and test constants, so nothing to change there.
Tested: setup.c compiles with llvm-mingw clang (no new warnings), and the Python files parse.
test_linux_update/test_make_game_*give the same results as main on Windows; the Linux-only cases run in CI.🤖 Generated with Claude Code
Thanks for this. The SHA-1
usedforsecurity=Falsechanges and thenext_line()replacement forstrtoklook right to me (same digests, so caches stay valid, andnext_linehandles CRLF, blank lines and the no-trailing-newline case as the description says). One real bug though, in the new https check:_requestis broken by a stray argument (inline comment below).urllib.request.Request(_https(url), url, headers=...)passesurla second time as the positionaldataargument. That turns the request into a POST with astrbody, andurlopenthen raisesTypeError: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.I reproduced it with Python 3.14:Request(u, u).get_method()isPOSTandurlopenraises. So every Linux update download through_request(the release-info fetch in_api_downloadand the plain-URL path) would fail.tests/test_linux_update.pydoesn't exercise_request/_api_download(nourlopenor_requestreferences), which is why nothing would catch this; a tiny test that mocksurllib.request.urlopenand checks that_request("https://...")succeeds and_request("http://...")raisesValueErrorwould cover it (and the same forrelease_parts.get).Smaller notes, none blocking:
HTTPRedirectHandlersubclass that re-runs_httpswould make the claim exact. It's a nit if you think the description already says enough.https://release URLs all pass, and nothing on Windows toucheslinux_update.py.release_parts.getis only called with https GitHub/llvm-mingw URLs in the workflows.0o755chmod only gets a comment (fine, it really is the intended mode), and the other changes change behaviour.Happy to re-check once the
Request(...)call is fixed.@ -210,3 +217,3 @@def _request(url, timeout, limit=MAX_DOWNLOAD):req = urllib.request.Request(url, headers={"User-Agent": "Hookshot", "Accept": "application/vnd.github+json"})req = urllib.request.Request(_https(url), url, headers={"User-Agent": "Hookshot", "Accept": "application/vnd.github+json"})with urllib.request.urlopen(req, timeout=timeout) as response:This passes
urltwice: the second positional argument ofRequestisdata, so this becomes a POST with a str body andurlopenraises TypeError. Should beurllib.request.Request(_https(url), headers={...}).