Building Secure Package Pipelines - André Silva, LexisNexis Risk Solutions

CNCF Youtube

Eliminating Secrets from Package Pipelines with OIDC

Most package publishing workflows still rely on long-lived API tokens stored as GitHub secrets. These tokens are high-value targets—compromise one and an attacker can push malicious versions of your package to npm, PyPI, or any other registry. OIDC-based authentication changes this model fundamentally by letting your CI environment prove its identity without storing any credentials.

The mechanism works through short-lived tokens issued by GitHub's OIDC provider. When your workflow runs, GitHub generates a JWT containing claims about the repository, branch, and workflow. Package registries like npm and PyPI can verify these tokens directly against GitHub's public keys. You configure the registry side once with your repository details, then workflows authenticate by requesting tokens on demand. No rotation schedules, no secret sprawl across repositories, no panic when someone leaves the team with lingering access.

The tradeoff is upfront configuration complexity. You need to set up trusted publishers in your registry, map repository identifiers correctly, and ensure your workflows request appropriate permissions. But this is one-time work that eliminates an entire class of credential theft attacks.

Cryptographic Build Attestations and SBOM Generation

Generating an SBOM for each release has moved from compliance checkbox to operational necessity. When a vulnerability drops in a transitive dependency, you need to know within minutes whether your artifacts are affected. Automated SBOM generation in CI—using tools like syft or the native capabilities in buildpacks—means this data exists before anyone asks for it.

Pair this with cryptographic attestations using sigstore or similar tooling. The pattern here is signing not just the final artifact but the entire provenance chain: which commit, which workflow, which dependencies at build time. This creates a verifiable audit trail. When you're investigating whether a compromised dependency made it into production, you can cryptographically verify what went into each build rather than trusting CI logs that could have been tampered with.

The practical implementation detail that matters: use in-toto attestation formats rather than proprietary signing schemes. This ensures your attestations remain verifiable even if you switch CI providers or signing infrastructure.

Hardening GitHub Actions with Hash Pinning

Pinning action versions to commit hashes instead of semantic versions addresses a specific attack vector: compromised action repositories or tag manipulation. When you reference actions/checkout@v4, you're trusting that the v4 tag points to safe code. An attacker with write access to that repository could retag v4 to malicious code. Pinning to actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab removes this trust assumption.

The operational cost is real—hash-pinned workflows don't automatically receive security updates. Dependabot can automate this, creating PRs when action repositories publish new versions, but you're adding review overhead. The calculus depends on your threat model. For public packages with millions of downloads, the paranoia is justified. For internal tooling, semantic version pinning with Dependabot updates might be sufficient.

Matrix testing across platforms catches architecture-specific issues before users do, but the security benefit is subtler: it reduces the window where platform-specific vulnerabilities exist in some published artifacts but not others. When you're publishing containers for amd64 and arm64, building and scanning both in CI means you're not shipping known CVEs to half your users.