Skip to content

ci: pin actions, least-privilege token, fix ruff install, pytest >=9.0.3 - #1

Merged
dzeusking-dev merged 1 commit into
mainfrom
claude/ci-supply-chain-hardening
Oct 30, 2026
Merged

dzeusking-dev merged 1 commit into
mainfrom
claude/ci-supply-chain-hardening

Conversation

@dzeusking-dev

Copy link
Copy Markdown
Contributor

Summary

Supply-chain hardening for CI after the October 2026 GitHub Actions credential-theft campaigns (GhostAction), plus one real CI bug and a pytest advisory.

1. Pin actions to a commit SHA. actions/checkout@v4 is now actions/checkout@11d5960a… (v4.4.0) in ci.yml (2×) and issue_create_auto_reply.yml. The major version is unchanged, so behaviour is unchanged. The SHA was verified against the v4 and v4.4.0 tags of actions/checkout, and it is the pin already used across the other gexiro-global repos. A mutable tag can be repointed to malicious code; a SHA cannot. Each checkout also sets persist-credentials: false, since no job pushes.

2. Least-privilege token. ci.yml had no permissions: block, so it inherited the repository default token scope. It now declares contents: read. issue_create_auto_reply.yml already restricted itself to issues: write and is unchanged apart from the pin.

3. Fix the ruff install (real bug). run: pip install ruff>=0.15.0 is unquoted, so bash parses >=0.15.0 as a stdout redirect. The version constraint was never applied, and pip's output went to a file called =0.15.0. Reproduced:

$ bash -e -c 'echo pip install ruff>=0.15.0'; ls
=0.15.0

It is now pip install "ruff==0.17.3" (exact pin). ruff check and ruff format --check with 0.17.3 pass locally on backend/app/ (all checks passed, 67 files already formatted).

4. pytest floor 8.0.0 → 9.0.3 (GHSA-6w46-j5rx-g56g, vulnerable tmpdir handling, fixed in 9.0.3). Applied in tests/requirements.txt, backend/pyproject.toml and ghostbill-python/pyproject.toml. pytest 9.0.3 requires Python ≥3.10, which all three projects already need.

Not changed here (follow-up)

pytest and pytest-asyncio are listed in backend/pyproject.toml [project].dependencies, and backend/Dockerfile runs pip install ., so the test framework ships in the production image. Moving them to an optional test extra changes how CI installs them in docker-compose.test.yml, so it belongs in its own PR.

Verification

  • Both workflow files parse as YAML.
  • ruff==0.17.3 lint and format checks pass on backend/app/.
  • Every pinned SHA was verified against the upstream tag.
  • CI on this PR.

Generated by Claude Code

- Pin actions/checkout to the v4.4.0 commit SHA in both workflows and
  stop persisting the token in the checkout.
- Add a top-level read-only permissions block to ci.yml.
- Quote the ruff requirement and pin it to 0.17.3. The unquoted
  'ruff>=0.15.0' was parsed by bash as a redirect, so the version spec
  was never applied and pip output went to a file named '=0.15.0'.
- Raise the pytest floor to 9.0.3 (GHSA-6w46-j5rx-g56g, vulnerable
  tmpdir handling) in tests/, backend/ and ghostbill-python/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016g7tG1VzB5Xnr8GJ7rGDti
@dzeusking-dev
dzeusking-dev marked this pull request as ready for review October 30, 2026 18:12
@dzeusking-dev
dzeusking-dev merged commit 2a7b2ff into main Oct 30, 2026
2 checks passed
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