Skip to content

GHA hardening - #1504

Open
erikd wants to merge 7 commits into
masterfrom
erikd/gha-hardening
Open

erikd wants to merge 7 commits into
masterfrom
erikd/gha-hardening

Conversation

@erikd

@erikd erikd commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

Context

Hardened as per recomendations in the cardano-parts repo.

Only touches CI, so no changelog entries needed.

How to trust this PR

CI passes.

Checklist

  • Commit sequence broadly makes sense and commits have useful messages
  • New tests are added if needed and existing tests are updated. See Running tests for more details
  • Self-reviewed the diff
  • Changelog fragment added in .changes/

erikd and others added 7 commits November 13, 2026 06:50
GitHub substitutes ${{ }} expressions into run: scripts before the
shell parses them, so any value containing shell metacharacters would
be executed. In particular, Release Upload expanded the target tag,
which comes from a free-form workflow_dispatch input or a pushed tag
name, unquoted into several scripts.

Pass these values (target tag, flake ref, matrix arch, base ref and the
concurrency group) through env: and reference them as quoted shell
variables.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Node.js 20 is deprecated on GitHub runners and these actions trigger a
warning on every run. Upgrade them, pinned to commit SHAs:

- actions/cache v4 -> v6.1.0
- actions/upload-artifact v4 -> v7.0.2
- actions/download-artifact v4 -> v8.0.2
- actions/stale v9 -> v11.0.0
- cardano-dev cabal-cache 0.0.1.1 -> 0.0.1.2, which moves to
  actions/cache v6.1.0.

input-output-hk/action-gh-release@v1 is an unmaintained fork that still
targets Node.js 16. Replace it with the gh CLI, as cardano-node's
release upload does. It keeps the same behaviour: attach to the
release for the tag if one exists (publishing a draft and updating its
title and notes), otherwise create it, and replace any existing assets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tags and branches are mutable and can be moved to point at different
code. Pin every action to the commit its tag (or the iohk actions
`latest` branch) currently resolves to, keeping the exact version as
a trailing comment, so behaviour is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The default persist-credentials: true writes the GITHUB_TOKEN into
.git/config, where every later step can read it. Turn it off for every
checkout that does not push with git: the gh-pages deploy passes its
own token to actions-gh-pages, the release job uploads with the gh CLI,
and fetching from this public repo needs no auth.

Three checkouts keep the default because they push with those
credentials: the release workflow (herald-release pushes the release
branch) and the Release Upload jobs that push and delete the ci/ branch
for Hydra.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
accept-flake-config lets a flake's nixConfig set arbitrary Nix options,
so a PR changing flake.nix could alter the CI Nix configuration. Set
the options from flake.nix's nixConfig (the cache.iog.io substituter
and allow-import-from-derivation) explicitly instead, as the other
workflows here already do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Default the token to read-only in every workflow that did not already
set permissions, and grant jobs only the write scopes they need:

- Close stale issues and PR: actions (state cache), issues and
  pull-requests write.
- Haddock documentation: contents write to push gh-pages.
- Check HLint: security-events write to upload code scanning results.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The version and branch inputs of the manually dispatched release
workflow are interpolated into shell scripts by herald-release. Reject
anything that is not an A.B.C.D version or a plain, valid branch name
before they get that far.

Release Upload's target tag can come from a free-form workflow_dispatch
input. Only accept a plain ref name before using it in file names, the
flake reference and the release.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@erikd
erikd requested a review from a team as a code owner November 12, 2026 20:06
Copilot AI balanced review requested due to automatic review settings November 12, 2026 20:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues remain for the GitHub Actions workflow-hardening changes.

No open issues 🎉

What changed in this PR

This PR hardens GitHub Actions workflows for cardano-cli’s CI, documentation, release automation, and repository maintenance without changing application code.

Changes:

  • Pins actions to commit hashes and updates selected action versions.
  • Sets explicit token permissions and disables persisted checkout credentials where unnecessary.
  • Validates release inputs, passes shell values through environment variables, and replaces the release-publishing action with GitHub CLI commands.
File Description
.github/​workflows/​stale-bot.yml Pins the stale action and scopes maintenance permissions.
.github/​workflows/​shellcheck.yml Pins actions and restricts checkout credentials and permissions.
.github/​workflows/​release.yml Validates inputs, pins actions, and explicitly configures Nix trust.
.github/​workflows/​release-upload.yml Hardens shell handling, updates artifact actions, and publishes through GitHub CLI.
.github/​workflows/​markdown-links-ci-check.yml Pins checkout and limits credentials and permissions.
.github/​workflows/​hls.yml Pins actions and safely passes the base branch to shell commands.
.github/​workflows/​haskell.yml Pins build and artifact actions and hardens environment handling.
.github/​workflows/​github-page.yml Scopes deployment permissions and pins documentation actions.
.github/​workflows/​check-pr-changelog.yml Pins validation actions and explicitly configures Nix trust.
.github/​workflows/​check-hlint.yml Pins actions and grants explicit code-scanning permissions.
.github/​workflows/​check-git-dependencies.yml Restricts permissions and disables persisted checkout credentials.
.github/​workflows/​check-formatting.yml Pins actions and quotes base-branch values in shell commands.
.github/​workflows/​check-cabal-gild.yml Pins actions and restricts credentials and permissions.
.github/​workflows/​check-cabal-files.yml Pins actions and restricts credentials and permissions.
.github/​workflows/​actionlint.yml Pins linting dependencies and restricts credentials and permissions.

Review effort: Balanced

This branch has not been deployed

No deployments
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