Skip to main content
RunBook Academy

Git, CI/CD & GitOpsXC · CI Platform SecurityRegistryAndSecrets

Registry and secret store access from CI — what registry and secret-store creds enable

Advanced⏱ ~25 mingit

What you'll learn

  • Explain what registry push and pull credentials enable from a CI runner
  • Explain what secret store read credentials enable from a CI runner
  • Distinguish tag-based image references from digest-based references and the deploy integrity gap
  • Configure per-job scoped registry tokens and digest-pinned deploys

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

Two credential classes converge in the CI: the registry credential that pushes the artifact the team deploys, and the secret store credential that reads the secrets the artifact needs at runtime. Both are production credentials because both reach production. The discipline is to scope both per-job and to bind the registry credential to a digest the deploy can verify.

What a registry credential enables

A registry credential on a CI runner can push to and pull from the team’s container registry. The two operations are different and need different controls:

flowchart TB
    REG["Registry credential"]
    REG --> P["Push"]
    REG --> G["Pull"]
    P --> R1["Replace image under existing tag"]
    P --> R2["Push new image under new tag"]
    P --> R3["Overwrite digest in mutable reference"]
    G --> R4["Read any image the credential can see"]

A push credential is an integrity primitive. The attacker who holds a push credential can replace the artifact the deploy expects: push a new image under the same tag the manifest references, or overwrite the digest the deploy trusts. The supply chain turns against itself — the deploy runs the attacker’s image because the registry says it is the right image.

A pull credential is an exfiltration primitive. The attacker who holds a pull credential can read every image the credential can see, including private images that contain proprietary code or compiled secrets.

Digest-pinning is the structural ceiling

The deploy must reference images by digest, not by tag. The digest is the SHA-256 hash of the image content; the digest is immutable; the registry cannot return a different image under the same digest:

flowchart LR
    A["Deploy manifest"] -->|"image: myapp@sha256:abc..."| B["Cluster"]
    B -->|"Pull by digest"| C["Registry"]
    C -->|"Returns matching image"| B
    C -->|"Mismatch"| X["Attacker's image: pull rejected"]

A push credential that replaces myapp:1.4.2 cannot replace myapp@sha256:abc... because the registry stores the digest as the content address. The deploy integrity holds because the reference is immutable.

What a secret store credential enables

A secret store credential on a CI runner can read every secret the workflow declared. The categories:

flowchart TB
    SC["Secret store credential"]
    SC --> R1["Read by path"]
    SC --> R2["List under prefix"]
    SC --> R3["Renew leases (Vault)"]
    SC --> R4["Rotate secrets (if privileged)"]

A read credential is a reconnaissance primitive. The attacker who reads the secret store at apply time can read every secret the workflow declared — and the workflow typically declares more secrets than the apply uses. A list credential is an inventory primitive. The attacker who lists the secret store can enumerate every path the prefix exposes. The discipline is to scope the credential to the paths the workflow requires and to audit every read against the workflow that performed it.

Verifying the registry and the secret store

Two verifications belong in every CI workflow that touches the registry or the secret store:

  • After the registry push: verify the digest of the pushed image. docker inspect --format='{index .RepoDigests 0}' myapp:1.4.2 returns the digest. The CI asserts the digest matches the digest the build produced.
  • Before the secret store read: verify the path the workflow is about to read. A read of secrets/data/db/prod/* is a read of every production database secret; a workflow that needs only secrets/data/db/prod/readonly should fail if it tries to read more.

Production discipline

  1. Digest-pinned deploys. The manifest references image@sha256:..., never image:tag. The digest is the integrity barrier.
  2. Per-job registry credentials. Push for the build job, scoped to the repository and tag namespace; pull for the deploy job, scoped to read-only. No long-lived registry tokens on the runner.
  3. Per-job secret store credentials. Each workflow gets a token scoped to the paths it needs. Vault dynamic secrets where supported.
  4. Verify the digest after push, the path before read. Catches the registry that served a different image and the secret store path that exposed more than declared.
  5. Rotate any secret the workflow read. A workflow that read a production secret has the secret’s lifetime in its audit window.

Cross-course references

  • Part XC-01 (What the CI platform can touch) maps the registry and secret store in the wider blast radius.
  • Docker for Production Sysadmins — Part XXXV (DockerSecurity) covers image signing and digest pinning.
  • Part XLII-04 (Environment scopes) covers the per-environment scoping pattern.
  • Part XLII-06 (The short-lived credential ideal) covers Vault dynamic secrets.

Quiz

Knowledge check · 4 questions

  1. Q1. A CI workflow pushes a container image to the production registry under tag `myapp:1.4.2`. The production deploy references the same tag. What is the integrity gap?

  2. Q2. Vault dynamic secrets remove the long-lived secret store credential from the CI runner by issuing a fresh credential per lease.

  3. Q3. Explain why tag-based image references are mutable and digest-based references are not, and what integrity property digest pinning gives the deploy.

  4. Q4. Diagnose a registry compromise that substituted a malicious image under a tag-based deploy reference, and prescribe the digest-pinning migration.

    Team T's production cluster deploys from manifests that reference `myapp:1.4.2` by tag. The CI holds a registry push token valid for the entire registry namespace. A fork PR opens; a malicious step uses the push token to overwrite the `myapp:1.4.2` tag with a backdoored image that runs a credential-stealer. The next production deploy pulls the backdoored image; the stealer exfiltrates the AWS credentials the workload reads at startup. The team's image-signing pipeline did not catch the substitution because the new image has a new digest.

Passing score: 75%. Answers are checked in this browser.