Skip to content

Security: harden CI workflows and composite actions - #43

Merged
frequency403 merged 2 commits into
developmentfrom
security/ci-hardening
Sep 28, 2026
Merged

frequency403 merged 2 commits into
developmentfrom
security/ci-hardening

Conversation

@frequency403

Copy link
Copy Markdown
Owner

Summary

Hardens the pipelines against supply-chain attacks and script injection.

  • Pin Actions to commit SHAs. All uses: now reference a commit SHA, with the tag kept as a comment for Dependabot/Renovate. This matters most for Actions that receive secrets:
    • rickstaa/action-create-tag gets PAT_TOKEN
    • KSXGitHub/github-actions-deploy-aur gets AUR_SSH_PRIVATE_KEY
    • vedantmgoyal9/winget-releaser@main gets WINGET_PUBLISH_TOKEN
    • peter-evans/repository-dispatch gets PAT_TOKEN
  • env instead of inline ${{ }} in run: blocks:
    • version-guard.yml: release_version comes from the csproj of the PR branch, and the part after - is not validated. It used to be inserted into bash and into Python source. It is now passed via env and os.environ.
    • deploy-aur: commit message, package name, flags and the SSH key are now passed via env. The key is written with umask 077.
    • deploy-release.yml: client_payload.version is passed via env and validated against X.Y.Z.
    • build-and-package.yml, build-appimage, determine-version: inputs are passed via env.
  • appimagetool was downloaded from the rolling continuous tag without any integrity check and then executed. It is now pinned to 1.9.1, which is the same commit as continuous today, and its SHA-256 is checked with sha256sum --check --strict.
  • permissions: contents: read added to test.yml, version-guard.yml, staging.yml and build-and-package.yml (a reusable workflow can only reduce permissions).
  • AUR fallback: StrictHostKeyChecking no changed to accept-new. See the reviewer questions.

Changes Made

  • Bug fix (non-breaking change)
  • New feature (non-breaking change)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Refactoring (no functional change)

Testing Performed

  • Tested on Windows (Version: _______)
  • Tested on macOS (Version: _______)
  • Tested on Linux (static checks only)
  • Added unit tests (if applicable)
  • Verified no regression in existing functionality

Test Evidence

  • actionlint 1.7.7 reports no new findings. The only remaining one is the unknown runner label ubuntu-slim, which exists on development too and is unknown to that actionlint version.
  • All composite actions were parsed with a YAML parser. No run: block contains an inline ${{ }} any more, and every script passes bash -n.
  • The sha256sum --check --strict line was tested with the correct and with a wrong hash (exit code 0 and 1).
  • The SHAs were resolved with git ls-remote; for annotated tags, the commit SHA (^{}) is used.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my code
  • Commented difficult areas
  • Updated documentation (if needed)
  • No new warnings/errors introduced
  • All builds pass locally (dotnet build, dotnet test) (no .NET changes)

Questions for Reviewers

  • AUR host key: accept-new is the same as no on a fresh runner. Real protection requires putting the published AUR host keys (ED25519/ECDSA/RSA) into known_hosts and using StrictHostKeyChecking yes. aur.archlinux.org was not reachable from the build environment, so the keys could not be verified and were not pinned.
  • appimagetool hash: it was computed from a download through a TLS-intercepting proxy. It should be cross-checked once against a direct download.
  • vedantmgoyal9/winget-releaser is pinned to the current main commit. There is no release tag for it.

Notes for Reviewers:

  • Priority: medium
  • Breaking change: no

🤖 Generated with Claude Code

https://claude.ai/code/session_01XSUJwZ17AWMdDvYXboJAbQ


Generated by Claude Code

claude and others added 2 commits September 28, 2026 12:41
- Pin all third-party and GitHub actions to commit SHAs (tag kept as
  comment); several of them receive PAT_TOKEN, AUR_SSH_PRIVATE_KEY and
  WINGET_PUBLISH_TOKEN.
- Pass inputs, event payload values and step outputs via env instead of
  inline ${{ }} expansion in run scripts (script injection), notably the
  PR-controlled release version in version-guard and the commit message
  and SSH key in the AUR fallback.
- Validate the version from the repository_dispatch payload.
- AUR fallback: write the key with umask 077, StrictHostKeyChecking
  accept-new instead of no.
- Pin appimagetool to 1.9.1 and verify its SHA-256 before executing it.
- Default the GITHUB_TOKEN to contents: read where no permissions were set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XSUJwZ17AWMdDvYXboJAbQ
@frequency403
frequency403 merged commit 45e8cb0 into development Sep 28, 2026
0 of 3 checks passed
@frequency403
frequency403 deleted the security/ci-hardening branch September 28, 2026 13:03
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.

2 participants