diff --git a/syft/pkg/cataloger/githubactions/package.go b/syft/pkg/cataloger/githubactions/package.go index 179957510..49c5c83e4 100644 --- a/syft/pkg/cataloger/githubactions/package.go +++ b/syft/pkg/cataloger/githubactions/package.go @@ -88,6 +88,13 @@ func packageURL(name, version string) string { var subPath string var namespace string + // docker:// references are OCI images, not GitHub repos. + // They don't fit the pkg:github PURL shape, so skip them entirely + // (same treatment as local composite actions below). + if strings.HasPrefix(name, "docker:") { + return "" + } + fields := strings.SplitN(name, "/", 3) switch len(fields) { case 1: diff --git a/syft/pkg/cataloger/githubactions/packageurl_test.go b/syft/pkg/cataloger/githubactions/packageurl_test.go new file mode 100644 index 000000000..4174c2026 --- /dev/null +++ b/syft/pkg/cataloger/githubactions/packageurl_test.go @@ -0,0 +1,23 @@ +package githubactions + +import "testing" + +func Test_packageURL_skipsDockerPrefix(t *testing.T) { + // docker:// references should return empty PURL (not a valid pkg:github) + got := packageURL("docker://ghcr.io/sethvargo/ratchet:latest", "sha256:527e78e6d29a9ac306e843cf766afe0604a0b35633f16913d85dd522218e8ca1") + if got != "" { + t.Errorf("packageURL(digest-form) = %q, want empty string", got) + } + + got = packageURL("docker://ghcr.io/some-org/some-action", "v1") + if got != "" { + t.Errorf("packageURL(tag-form) = %q, want empty string", got) + } + + // Sanity: regular github actions still work + got = packageURL("actions/checkout", "v4") + want := "pkg:github/actions/checkout@v4" + if got != want { + t.Errorf("packageURL(regular) = %q, want %q", got, want) + } +} diff --git a/syft/pkg/cataloger/githubactions/testdata/workflow-with-docker-actions.yaml b/syft/pkg/cataloger/githubactions/testdata/workflow-with-docker-actions.yaml new file mode 100644 index 000000000..c33a3d54b --- /dev/null +++ b/syft/pkg/cataloger/githubactions/testdata/workflow-with-docker-actions.yaml @@ -0,0 +1,10 @@ +name: "Docker Actions Test" +on: [push] +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: docker://ghcr.io/sethvargo/ratchet:latest@sha256:527e78e6d29a9ac306e843cf766afe0604a0b35633f16913d85dd522218e8ca1 + - uses: docker://ghcr.io/some-org/some-action@v1 + - uses: actions/setup-go@v5