#5299·syft

github-actions cataloger emits an invalid PURL for docker:// use statements

Author: asomyaCreated Sep 17, 2026Updated Sep 17, 2026
Labelsbuggood-first-issue

What happened:

The github-actions cataloger builds a pkg:github PURL for every uses: statement, including docker:// image references. packageURL() splits the name on / assuming an owner/repo path, so docker://ghcr.io/sethvargo/ratchet:latest produces namespace docker:, an empty name, and the image reference stranded in the subpath:

pkg:github/docker%3A/@sha256%3A527e78e6d29a...#ghcr.io/sethvargo/ratchet:latest

packageurl.FromString() rejects this string: purl is missing name. Syft is emitting a PURL its own parser will not read.

What you expected to happen:

A docker:// use statement references an OCI image, not a GitHub repo, so pkg:github is the wrong type. Either a valid image PURL:

pkg:oci/ratchet@sha256%3A527e78e6d29a...?repository_url=ghcr.io%2Fsethvargo&tag=latest

or no PURL at all — which the cataloger already does for local composite actions (namespace == "."return ""). Whichever type is chosen, the output should round-trip through packageurl-go.

Steps to reproduce the issue:

bash
mkdir -p /tmp/ghrepro/.github/workflows
printf 'on: [push]\njobs:\n  build:\n    steps:\n      - uses: actions/checkout@v4\n      - uses: docker://ghcr.io/sethvargo/ratchet:latest@sha256:527e78e6d29a9ac306e843cf766afe0604a0b35633f16913d85dd522218e8ca1\n' \
  > /tmp/ghrepro/.github/workflows/test.yml

syft scan dir:/tmp/ghrepro -o syft-json | jq -r '.artifacts[] | "\(.name)\t\(.purl)"'
actions/checkout                            pkg:github/actions/checkout@v4
docker://ghcr.io/sethvargo/ratchet:latest   pkg:github/docker%3A/@sha256%3A527e78e6d29a...#ghcr.io/sethvargo/ratchet:latest

The actions/checkout line is the control — same cataloger, valid PURL.

Anything else we need to know?:

  • Source: packageURL() in syft/pkg/cataloger/githubactions/package.go.
  • The no-digest form (uses: docker://ghcr.io/sethvargo/ratchet:latest) has no digest to put in the oci version field, which the purl spec requires — so that case may want pkg:docker or no PURL.
  • Downstream impact: consumers that key on the PURL lose every identifying token. The name is empty and the registry/org/repo only exist in the subpath, which anything comparing base PURLs discards. Container-based actions are documented Actions syntax, so this isn't an exotic input.

Environment:

  • Output of syft version: 1.52.0 (also reproduced on 1.49.0; the cataloger is unchanged since at least v1.38.0)
  • OS: macOS, darwin/arm64