You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up to #304, which hardened the CI installs against lifecycle-script execution but deliberately left the 4 githubactions:S8544 findings open. SonarCloud still reports them on .github/workflows/tests.yml at L156, L157, L604, L605 (the two pip install -r ... lines in each of test-github and test-forgejo).
Why it was deferred
requirements.txt and requirements-test.txt use >= ranges throughout. Satisfying S8544 means installing from a fully resolved, hash-pinned file, which is a dependency-management decision rather than a workflow edit. Folding it into a workflow-only PR would have made neither part reviewable.
Proposed approach
Adopt the pip-compile convention, which is also the layout Dependabot recognizes for lock updates:
requirements.in / requirements-test.in hold the human-edited >= ranges (the current file contents, moved)
requirements.txt / requirements-test.txt become pip-compile --generate-hashes output: every direct and transitive dependency pinned with hashes
This is a real security gain beyond satisfying the rule: hashes mean a compromised or substituted PyPI artifact fails the install rather than executing.
Constraint that shapes the design
tests/test_requirements.py parses requirements.txt for >= lines and asserts CVE-driven minimum floors:
asyncssh >= 2.14.2
cryptography >= 48.0.1
jinja2 >= 3.1.6
python-multipart >= 0.0.31
If requirements.txt becomes the compiled ==-pinned output, parse_requirements() returns an empty dict and the test fails on its first assert. The test must be retargeted to read requirements.in, where the ranges will live. Those floors are security bounds and must keep being enforced, not dropped.
Blast radius of the rename
Every reference to the requirements files needs review:
.github/workflows/tests.yml (4 install refs plus 2 hashFiles() cache keys)
The current floating ranges mean CI surfaces upstream breakage the day it ships. Hash-locking removes that early warning until Dependabot bumps the lock. The weekly grouped pip Dependabot schedule already in .github/dependabot.yml is what keeps the lag bounded, and it should be confirmed to actually update the compiled files.
Done when
pip-compile --generate-hashes lock files are committed and CI installs with --require-hashes
tests/test_requirements.py enforces the same CVE floors against requirements.in and passes
All four githubactions:S8544 findings are cleared on the analysis
Dependabot is confirmed to update the compiled files, or the config is adjusted so it does
Follow-up to #304, which hardened the CI installs against lifecycle-script execution but deliberately left the 4
githubactions:S8544findings open. SonarCloud still reports them on.github/workflows/tests.ymlat L156, L157, L604, L605 (the twopip install -r ...lines in each oftest-githubandtest-forgejo).Why it was deferred
requirements.txtandrequirements-test.txtuse>=ranges throughout. Satisfying S8544 means installing from a fully resolved, hash-pinned file, which is a dependency-management decision rather than a workflow edit. Folding it into a workflow-only PR would have made neither part reviewable.Proposed approach
Adopt the pip-compile convention, which is also the layout Dependabot recognizes for lock updates:
requirements.in/requirements-test.inhold the human-edited>=ranges (the current file contents, moved)requirements.txt/requirements-test.txtbecomepip-compile --generate-hashesoutput: every direct and transitive dependency pinned with hashespip install --require-hashes -r requirements.txt, alongside the--only-binary :all:flag added in Harden CI dependency installs against lifecycle-script execution #304This is a real security gain beyond satisfying the rule: hashes mean a compromised or substituted PyPI artifact fails the install rather than executing.
Constraint that shapes the design
tests/test_requirements.pyparsesrequirements.txtfor>=lines and asserts CVE-driven minimum floors:asyncssh >= 2.14.2cryptography >= 48.0.1jinja2 >= 3.1.6python-multipart >= 0.0.31If
requirements.txtbecomes the compiled==-pinned output,parse_requirements()returns an empty dict and the test fails on its first assert. The test must be retargeted to readrequirements.in, where the ranges will live. Those floors are security bounds and must keep being enforced, not dropped.Blast radius of the rename
Every reference to the requirements files needs review:
.github/workflows/tests.yml(4 install refs plus 2hashFiles()cache keys)Dockerfile(3 refs)start.sh.github/dependabot.ymltests/test_requirements.pydocs/TESTING.md,docs/ARCHITECTURE.md,CONTRIBUTING.mdTradeoff to accept explicitly
The current floating ranges mean CI surfaces upstream breakage the day it ships. Hash-locking removes that early warning until Dependabot bumps the lock. The weekly grouped
pipDependabot schedule already in.github/dependabot.ymlis what keeps the lag bounded, and it should be confirmed to actually update the compiled files.Done when
pip-compile --generate-hasheslock files are committed and CI installs with--require-hashestests/test_requirements.pyenforces the same CVE floors againstrequirements.inand passesgithubactions:S8544findings are cleared on the analysis