Skip to content
Latchkey

What Is a Secret in CI?

A CI secret is a sensitive value - an API token, a deploy key, a password - stored encrypted and injected into a job only when it runs.

Pipelines often need credentials to deploy, publish, or call APIs. Hard-coding those in the repo would expose them to anyone with read access. Secrets store such values encrypted and surface them to jobs as environment variables or inputs at runtime.

How secrets are stored and used

You add a secret in the platform UI or API; it is encrypted at rest. A workflow references it - for example ${{ secrets.NPM_TOKEN }} - and the platform injects the value into the job's environment for the duration of the run.

Scoping and access

  • Secrets can be scoped to a repo, an organization, or a deployment environment.
  • Environment secrets can require an approval before they are exposed.
  • Pull requests from forks are usually denied access to secrets.

A small example

A publish step reads NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} from the environment. The token never appears in the repo or the logs, and only runs on the protected branch where the secret is in scope.

Why forks are restricted

A pull request from a fork runs attacker-controllable code. If it could read your secrets, anyone could open a PR that exfiltrates them. That is why secrets are withheld from fork PRs by default - a key CI security boundary.

Best practices

Prefer OIDC over stored cloud keys where possible, give each secret the narrowest scope, rotate them regularly, and never echo a secret to logs. The platform masks known secret values, but constructed strings can still leak.

Key takeaways

  • A secret is a sensitive value stored encrypted and injected at runtime.
  • Scope secrets to repo, org, or environment, and deny forks access.
  • Prefer OIDC, rotate often, and never print secrets to logs.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →