DevSecOps

GitHub Packages Security Features: What You Get and What You Do Not

GitHub Packages integrates tightly with GitHub Actions and repositories. Its security features are convenient but have gaps that teams need to understand.

James
DevSecOps Engineer
6 min read

GitHub Packages has evolved from an afterthought into a legitimate artifact registry. It supports Docker images, npm packages, Maven artifacts, NuGet packages, and RubyGems, all tightly integrated with GitHub's repository and Actions infrastructure. For teams already on GitHub, the convenience factor is hard to beat.

But convenience and security are different things. GitHub Packages has real security features, and it has real gaps. Knowing the difference is essential for making informed decisions about your artifact supply chain.

Access Control Model

GitHub Packages ties access control to GitHub's existing permission model. This is both its strength and its limitation.

Repository-Linked Packages

Packages linked to a repository inherit the repository's visibility and access settings. A package in a private repository is only accessible to users who have at least read access to that repository. This is straightforward but means package access is coupled to code access, which may not match your organizational needs.

A developer who needs to pull a package dependency should not necessarily have read access to the source repository that produced it. GitHub Packages does not provide a clean separation between "can use this package" and "can read the source code."

Organization-Level Packages

GitHub Container Registry (ghcr.io) supports packages scoped to an organization rather than a specific repository. These packages have their own access settings independent of any repository. This provides more flexibility but requires manual access management.

Personal Access Tokens vs. GITHUB_TOKEN

For CI/CD pipelines in GitHub Actions, the automatically provided GITHUB_TOKEN is the right choice. It is scoped to the repository running the workflow and automatically expires when the workflow completes.

For external access, personal access tokens (PATs) or fine-grained tokens are required. Fine-grained tokens are preferable because they can be scoped to specific repositories and specific permissions. Classic PATs grant broader access and should be avoided.

Vulnerability Scanning

Dependabot and Security Advisories

GitHub automatically scans package manifests in repositories and generates Dependabot alerts for known vulnerabilities. This covers npm, Maven, pip, NuGet, and other package types.

However, Dependabot scans the dependency manifests in your source code, not the artifacts stored in GitHub Packages. If someone publishes a vulnerable package to GitHub Packages, Dependabot alerts the consumers of that package through their dependency files, not through the package registry itself.

Container Image Scanning

For Docker images stored in ghcr.io, GitHub does not provide built-in vulnerability scanning comparable to AWS ECR or Azure ACR. You need to integrate a third-party scanner into your GitHub Actions workflow to scan images before or after pushing them.

- name: Scan container image
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: ghcr.io/${{ github.repository }}:${{ github.sha }}
    format: table
    exit-code: 1
    severity: CRITICAL,HIGH

This is a gap. Other registry providers scan images automatically. With GitHub Packages, you build the scanning pipeline yourself.

Code Scanning and SARIF

GitHub's code scanning feature accepts SARIF results from any security tool. You can upload vulnerability scan results for packages and view them in the repository's Security tab. This provides a unified view of security findings but requires explicit integration work.

Supply Chain Security Features

Artifact Attestations

GitHub supports artifact attestations through the attest-build-provenance action, which generates SLSA provenance attestations for your build artifacts. These attestations are stored alongside the artifact and can be verified with GitHub's gh attestation verify command.

This is a strong feature for establishing build provenance. It proves that a specific artifact was built by a specific GitHub Actions workflow from a specific commit. Consumers can verify these attestations before using the package.

Sigstore Integration

GitHub Actions workflows generate Sigstore-compatible signing certificates automatically through the sigstore/cosign-installer action. Combined with keyless signing, this provides strong integrity guarantees for container images pushed to ghcr.io.

Dependency Review

The dependency review action scans pull requests for dependency changes and blocks merging if new dependencies introduce known vulnerabilities. This is a proactive control that prevents vulnerable dependencies from entering your codebase.

What GitHub Packages Does Not Provide

No Built-In Content Trust

GitHub Packages does not have a Docker Content Trust equivalent. There is no registry-level enforcement that prevents pulling unsigned images. You can sign images with Cosign and verify in your deployment pipeline, but the registry itself does not enforce signing.

No Download Prevention Based on Vulnerabilities

Unlike Harbor or Artifactory, GitHub Packages cannot block the download of packages that have known vulnerabilities. You can fail your CI/CD pipeline, but the package remains pullable by anyone with access.

Limited Audit Logging

GitHub's audit log covers organization-level events but provides limited visibility into individual package pull events. You know when packages are published and when permissions change, but tracking who pulled what package and when is more difficult.

No Repository Proxy/Cache

GitHub Packages does not function as a proxy cache for upstream registries. You cannot use it to cache Docker Hub images or npm packages locally. This means you remain dependent on upstream registry availability and are subject to their rate limits.

Best Practices

Use Fine-Grained Tokens

Replace any classic PATs used for package access with fine-grained tokens. Scope them to the minimum repositories and permissions needed.

Sign Your Container Images

Integrate Cosign signing into your GitHub Actions workflow. Even though ghcr.io does not enforce signing, establishing the practice now prepares you for enforcement later.

Scan Before Publishing

Add vulnerability scanning as a required step before publishing packages. Fail the workflow if critical vulnerabilities are found. Do not publish vulnerable artifacts to your registry.

Monitor Package Access

Use GitHub's audit log API to track package-related events. Alert on unexpected package publications, permission changes, and access from new IP ranges.

How Safeguard.sh Helps

Safeguard.sh fills the security gaps in GitHub Packages by providing continuous vulnerability scanning for container images and packages stored in ghcr.io, generating comprehensive SBOMs that go beyond what Dependabot tracks, and enforcing security policies that GitHub Packages does not natively support. When you need to know which of your GitHub Packages contain a newly disclosed vulnerability, Safeguard.sh provides that answer across your entire artifact inventory.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.