Skip to content

Harden GitHub Actions supply chain - #143

Merged
MarkusPaulsen merged 1 commit into
mainfrom
chore/actions-supply-chain-hardening
Jul 21, 2026
Merged

Harden GitHub Actions supply chain#143
MarkusPaulsen merged 1 commit into
mainfrom
chore/actions-supply-chain-hardening

Conversation

@MarkusPaulsen

@MarkusPaulsen MarkusPaulsen commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

Pins every GitHub Actions reference in this repository to an immutable commit SHA and groups Dependabot security updates per ecosystem.
A version tag such as v7 is mutable and can be repointed by its upstream owner at any time, so a compromised action repository would execute inside Ares' CI without any change landing here.
This closes that gap for the pipeline that gates every change to a security-enforcement library.

Linked issues

None.

1. Problem

This pull request is not driven by a defect in Ares' behaviour, so it changes neither a false negative nor a false positive. It closes a gap in the build integration layer, not in the policy layer, the generated security test or the enforcement layer.

Before this change, 16 of the 18 uses: references across .github/workflows named a mutable Git tag, for example actions/checkout@v7 and github/codeql-action/init@v4. Only pullrequest-labeler.yml and issue-labeler.yml already pinned to a commit SHA.

A tag is a movable pointer owned by the action's publisher. Anyone who gains write access to one of those upstream repositories, or the publisher themselves, can repoint v7 at a different commit, and the next CI run here executes that commit. The observed configuration does not matter, since this holds for every job in every workflow, on every operating system and JDK.

The expected behaviour is that a given commit of Ares always builds and tests with exactly the third-party code it was reviewed against, so that a CI run is reproducible and an upstream compromise cannot reach this repository without a visible diff.

Why it matters for Ares specifically: this CI is what decides whether a change to a security boundary is fit to merge. Its jobs hold a GITHUB_TOKEN and run on the runner alongside the checked-out source. An attacker controlling any action in the graph could alter test results, so a run could report green while the enforcement logic no longer rejects what it is meant to reject. The credibility of the merge gate depends on the integrity of the actions it runs.

A secondary, smaller problem: Dependabot currently opens one pull request per vulnerable dependency, which spreads a single security event across several reviews.

2. Improvement from the user's perspective

Instructors ship Ares inside an exercise test repository and students submit code that runs under it. Neither group interacts with this change directly, and no policy option, failure message or runtime behaviour changes.

The indirect benefit is the trustworthiness of the merge gate that protects them: from now on, a green CI run on Ares means the enforcement logic was verified by third-party code at commits that were reviewed when they were pinned, rather than by whatever those tags point at on the day of the run. Note that release publishing does not happen in this workflow, so this pull request hardens the pipeline that gates changes, not the release path itself.

3. Improvement from the maintainer's perspective

CI runs become reproducible. Re-running an old workflow now resolves the same third-party code it originally used, so a build that changes behaviour points at a change in this repository rather than at a silent upstream tag move.

Upstream changes become reviewable. Dependabot already tracks the github-actions ecosystem weekly, so each bump now arrives as an explicit diff of a SHA and its version comment, instead of arriving invisibly.

Review load for vulnerabilities drops. Grouping security updates per ecosystem turns a batch of vulnerability fixes into one pull request instead of several. Version updates deliberately stay ungrouped, so a routine bump that breaks the build can still be reverted on its own.

Finally, this makes the repository consistent: two workflows already pinned to SHAs and the rest did not.

4. Testing manual

Prerequisites

  1. Nothing to install. The change is verified from this pull request's own workflow runs, not from an exercise.

Steps

Not reproducible from an exercise. This pull request changes only CI configuration, so a reviewer verifies it as follows:

  1. Open the Checks tab of this pull request and confirm that all five workflows completed successfully, in particular CodeQL, which now resolves github/codeql-action from a commit SHA, and Lint GitHub Workflows.
  2. Review the diff and confirm that every + line of the form uses: …@<sha> carries a 40-character hexadecimal SHA followed by a semver comment, matching the convention already used in pullrequest-labeler.yml.
  3. Spot-check that a pinned SHA really belongs to the claimed version, for example gh api repos/actions/checkout/tags --jq '.[] | select(.commit.sha=="3d3c42e5aac5ba805825da76410c181273ba90b1") | .name', which must list v7.0.1.
  4. Confirm no mutable reference remains: grep -rnE 'uses:[[:space:]]*[^[:space:]]+@(v[0-9]|main|master)' .github/ must print nothing.
  5. Confirm .github/dependabot.yml declares one applies-to: security-updates group per ecosystem and leaves version updates ungrouped.

Expected result

All five checks are green. Every action reference resolves to a commit SHA whose version comment matches the tag that upstream actually points at, and no mutable reference is left in .github/.

Negative case (what must still be rejected)

  1. The repository setting allowed_actions is now selected, permitting GitHub-owned actions plus the pattern MaximilianAnzinger/issue-labeler@* only. A workflow that introduces any other third-party action must be refused at run start rather than executed. A reviewer can confirm the policy with gh api repos/ls1intum/Ares2/actions/permissions/selected-actions, which must report verified_allowed: false.
  2. After merge, once sha_pinning_required is enabled (see below), a workflow that reintroduces a mutable tag must fail to start. Until then, nothing enforces the pinning, so the reviewer's check in step 4 is what protects it.
  3. This pull request must not have relaxed anything: default_workflow_permissions must still be read and can_approve_pull_request_reviews must still be false.

Modes exercised

No mode-specific behaviour changed. The change touches no Java code and cannot alter what the enforcement layer accepts or rejects. The full Java CI with Maven matrix nonetheless ran and passed on this branch.

  • ArchUnit + AspectJ
  • ArchUnit + instrumentation
  • WALA + AspectJ
  • WALA + instrumentation

5. Test case coverage regarding this PR

No Java code changed.

Breaking changes and migration

None.

The public API under de.tum.cit.ase.ares.api, the security policy file format and its schema, the generated security test code and the minimum JDK, Maven and Gradle versions are all untouched. Instructors need to do nothing.

Accompanying repository settings

Not part of the diff, because these are repository settings rather than version-controlled files. Recorded here so the change is reviewable:

  • allowed_actions set to selected, permitting GitHub-owned actions plus MaximilianAnzinger/issue-labeler@*, with verified_allowed: false.
  • Approval for fork pull request workflows tightened from first_time_contributors to all_external_contributors.
  • A new ruleset protecting all tags against deletion and force pushes.
  • Confirmed already correct and left unchanged: default_workflow_permissions: read and can_approve_pull_request_reviews: false.

Follow-up after merge: the repository flag sha_pinning_required is still false and should be set to true once this lands. Enabling it beforehand would block every workflow run whose uses: still names a mutable tag, including runs on main and on open feature branches.

Checklist

  • CI is green, or every remaining failure is explained above.
  • No secrets, tokens or absolute local paths are contained in the diff.

Review progress

  • Code review
  • Manual test

Pin all action references to full commit SHAs with semver comments,
following the convention already used in pullrequest-labeler.yml. A
mutable tag such as v7 can be repointed by the upstream owner, so a
compromised action repository would execute in this repo's CI without
any change landing here.

Group Dependabot security updates per ecosystem so that a batch of
vulnerability fixes arrives as one reviewable pull request instead of
many. Version updates stay ungrouped to keep routine bumps individually
revertible.
Copilot AI review requested due to automatic review settings July 21, 2026 12:00
@MarkusPaulsen
MarkusPaulsen requested review from a team and krusche as code owners July 21, 2026 12:00
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@MarkusPaulsen, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 31 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 7c7041df-6083-4ed0-aad2-af095ae272ae

📥 Commits

Reviewing files that changed from the base of the PR and between bfde084 and d16196a.

📒 Files selected for processing (4)
  • .github/dependabot.yml
  • .github/workflows/actionlint.yml
  • .github/workflows/codeql.yml
  • .github/workflows/maven.yml
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/actions-supply-chain-hardening

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the other Automated area label: other label Jul 21, 2026

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.

Pull request overview

This PR hardens the CI supply chain by eliminating mutable GitHub Actions tag references and batching Dependabot security updates, reducing the risk of upstream action tag repoints and decreasing PR noise from vulnerability fix rollups.

Changes:

  • Pinned all GitHub Actions uses: references in workflows to full commit SHAs with semver comments.
  • Pinned CodeQL init/analyze actions to a commit SHA (instead of a mutable v4 tag).
  • Added Dependabot grouping for security updates only (per ecosystem), leaving version updates ungrouped.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
.github/workflows/maven.yml Pins checkout/setup-java/upload-artifact actions to commit SHAs across all jobs.
.github/workflows/codeql.yml Pins checkout/setup-java and CodeQL actions to commit SHAs for immutable CI execution.
.github/workflows/actionlint.yml Pins checkout action to a commit SHA to avoid mutable tag execution.
.github/dependabot.yml Adds security-update grouping for Maven and GitHub Actions ecosystems.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@MarkusPaulsen

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@ShudongCai ShudongCai 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.

Code LGTM

@MarkusPaulsen
MarkusPaulsen merged commit 6a3c9a6 into main Jul 21, 2026
13 of 14 checks passed
@MarkusPaulsen
MarkusPaulsen deleted the chore/actions-supply-chain-hardening branch July 21, 2026 14:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

other Automated area label: other

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants