Skip to content

feat: add commit reachability checks - #2

Merged
nodeselector merged 4 commits into
mainfrom
ns/reachability-checks
Apr 23, 2026
Merged

feat: add commit reachability checks#2
nodeselector merged 4 commits into
mainfrom
ns/reachability-checks

Conversation

@nodeselector

@nodeselector nodeselector commented Apr 23, 2026

Copy link
Copy Markdown
Collaborator

too expensive to do during job invocation time but we could do it at pin time & at ci time. this isn't a 100% fix to the situation at all by any means but it does harden our position. for example, here's me avoiding the latest trivy compromise:

gh actions-pin check .github/workflows/boot-warning.yml  
Re-resolving 2 action reference(s)...
Checking commit reachability for 2 dependency(ies)...
error: [TAMPERED] aquasecurity/setup-trivy@v0.2.6: expected c19401b2f58dc6d2632cb473d44be98dd8292a93 but live resolution is 3fb12ec12f41e471780db15c232d5dd185dcb514
error: [UNREACHABLE] aquasecurity/setup-trivy@v0.2.6: SHA c19401b2f58d is not reachable from ref v0.2.6 (no common ancestor or commit not found)

Sample workflow:

name: dependencies simple
on:
  push:
  workflow_dispatch: 
jobs:
  test:
    runs-on: self-hosted
    steps:
      - uses: actions/checkout@v4
      - uses: nodeselector/actions-test-fixtures/nested-composite@v1
      - uses: nodeselector/actions-test-fixtures/nested-composite@v2
      - uses: aquasecurity/setup-trivy@v0.2.6
  reusable-workflow:
    uses: bbq-beets/nodeselector/.github/workflows/reusable.yaml@main

# Automatically generated and managed by: `gh actions pin <workflow-path>`
dependencies:
  - github.com/actions/checkout@v4:sha1-34e114876b0b11c390a56381ad16ebd13914f8d5
  - github.com/nodeselector/actions-test-fixtures-b/simple-echo@main:sha1-92b7b0058bc223c6e9dd4e19ef9247c934ba7637
  - github.com/nodeselector/actions-test-fixtures/nested-composite@v1:sha1-ea53476fdc172d8552df5af9658a45a367e4f41d
  - github.com/nodeselector/actions-test-fixtures/nested-composite@v2:sha1-fbe04216bcc00ebe76c49276d4b8ee066a21ef22
  - github.com/nodeselector/actions-test-fixtures/simple-composite@main:sha1-fbe04216bcc00ebe76c49276d4b8ee066a21ef22
  - github.com/nodeselector/actions-test-fixtures/simple-node@main:sha1-fbe04216bcc00ebe76c49276d4b8ee066a21ef22
  - github.com/aquasecurity/setup-trivy@v0.2.6:sha1-c19401b2f58dc6d2632cb473d44be98dd8292a93

@nodeselector
nodeselector force-pushed the ns/reachability-checks branch 2 times, most recently from d01ae41 to 73dbd1b Compare April 23, 2026 21:44
@nodeselector
nodeselector marked this pull request as ready for review April 23, 2026 21:49
Copilot AI review requested due to automatic review settings April 23, 2026 21:49

Copilot AI left a comment

Copy link
Copy Markdown

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 gh-actions-pin against supply-chain attacks by adding commit reachability verification: ensuring the pinned SHA is actually on the lineage of the referenced tag/branch in the canonical repository (detecting fork-network injection/tag poisoning patterns).

Changes:

  • Add REST-based reachability checks using GitHub’s Compare API (with caching + test override hook).
  • Surface reachability results during pin (warn-only) and check (validation error on unreachable; warning on unknown).
  • Expand unit/integration test coverage and extend the HTTP mock helper to support REST endpoints.
Show a summary per file
File Description
root.go Adds reachability validation/warnings to pin and check, plus new output/skip behavior.
internal/resolver/resolver.go Introduces REST client + reachability API (Compare API) with caching and batch helper.
internal/resolver/resolver_test.go Adds unit tests for reachability behavior (reachable/unreachable/unknown/caching/dedup).
internal/resolver/reachability_integration_test.go Adds live integration tests (tagged integration) against real GitHub fixtures.
internal/httpmock/httpmock.go Adds REST request matcher and status responder to support Compare API tests.
command_test.go Adapts command harness to inject reachability behavior; adds end-to-end “tampered/unreachable” style tests.

Copilot's findings

Tip

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

  • Files reviewed: 6/6 changed files
  • Comments generated: 4

Comment thread internal/resolver/resolver.go
Comment thread root.go Outdated
Comment thread root.go
Comment thread root.go

Copilot AI commented Apr 23, 2026

Copy link
Copy Markdown

Warning

This is an internal experiment to assess Copilot's ability to auto-approve PRs. Please 👍 this comment if the assessment below is correct and 👎 if not. Feedback in #f-ccr-auto-approve is appreciated!

Copilot thinks this PR is not ready to approve — see review comments for details.

@nodeselector
nodeselector force-pushed the ns/reachability-checks branch from 789256a to bad5127 Compare April 23, 2026 22:50
nodeselector and others added 4 commits April 23, 2026 17:52
Adds reachability verification using the GitHub compare API to catch
supply chain attacks where a SHA exists in the shared object store but
is not on the canonical repository's lineage.

Detection:
- check command: UNREACHABLE = validation failure (fail-closed)
- pin/upgrade commands: UNREACHABLE = warning only (defense-in-depth)
- API errors (rate limit, 500) = Unknown, warn but don't block

Tests model 4 real-world supply chain attacks:
- tj-actions/changed-files (CVE-2025-30066)
- reviewdog/action-setup (CVE-2025-30154)
- aquasecurity/trivy-action (CVE-2026-33634)
- Checkmarx KICS (TeamPCP lateral movement)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Uses nodeselector/actions-test-fixtures with:
- tag v1 on main HEAD (identical → reachable)
- root commit of main (ancestor → reachable)
- orphan-poison branch commit (no common ancestor → unreachable)
- fabricated SHA (404 → unreachable)
- cache consistency verification

Guarded by //go:build integration — won't run without -tags integration.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- URL-escape ref and SHA in Compare API path to handle refs with slashes
  (e.g. feature/foo) that would break the URL path segments
- Add DepKey field to ReachabilityResult and thread dep.Key() through
  CheckReachabilityAll so error messages include the full dependency key
  including subpath (e.g. actions/cache/save@v4 not actions/cache@v4)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@nodeselector
nodeselector force-pushed the ns/reachability-checks branch from bad5127 to 2bba3eb Compare April 23, 2026 22:54
@nodeselector
nodeselector merged commit fbc661f into main Apr 23, 2026
5 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.

2 participants