CI Permission Model
What can CI do? Bound it.
Least privilege
The CI system is one of the highest-privilege actors in any engineering org. It can deploy to production, push to artifact registries, modify cloud infrastructure, and access internal APIs. The principle of least privilege says the CI should have only the permissions strictly required for the job it is currently running. The default of "give CI broad credentials so any pipeline can do anything" is the security posture that produces breach-class incidents.
What least privilege looks like in CI:
- CI gets only what it needs.: A build pipeline gets read access to the source repo and write access to the artifact registry. A deploy pipeline gets read on the registry and deploy permissions on the target environment. A test pipeline gets none of the production credentials. The permissions match the job; nothing extra.
- Per-pipeline scope.: Each pipeline declares the credentials it requires in its config. The CI system enforces the declaration: if a pipeline tries to use a credential not on its allowlist, the call is denied. This is the property that makes "least privilege" enforceable rather than aspirational.
- Per-environment separation.: Dev deploy credentials cannot deploy to staging. Staging credentials cannot deploy to prod. The credentials are scoped to the environment they are meant to act on. Compromising a dev pipeline does not give an attacker a path to production.
- Production credentials require additional gates.: Pipelines that touch production credentials require manual approval, additional review, or a specific protected branch. The most powerful credentials have the most friction to use, which keeps casual misuse impossible.
- Read-only by default.: The CI's default credential scope is read-only. Write access requires explicit declaration and explicit allowlisting. Most CI work (lint, type-check, unit test) needs only read access; restricting that to read-only catches a whole class of accidents.
The cost of least privilege is some extra config per pipeline. The benefit is that a compromised pipeline has bounded blast radius. The math is heavily in favor of the discipline.
OIDC
The historic way CI authenticated to cloud providers and internal services was with long-lived secrets stored in CI as environment variables. That model is being replaced by OIDC (OpenID Connect): the CI system mints a short-lived, per-job token that the cloud provider trusts based on the CI's identity claims. No standing credentials, no secrets to leak, no rotation problems.
- Short-lived per-job tokens.: Every CI job receives a freshly-minted JWT signed by the CI provider. The token has a lifetime measured in minutes (typically 15 to 60). When the job ends, the token is gone. No long-lived secret exists to be exfiltrated.
- No standing credentials.: The CI does not store AWS access keys, GCP service account JSON, or any other long-lived credential. The credential exists only in the running job's memory, only for the duration of that job. Eliminating standing credentials closes the most common cloud breach vector.
- Identity-based trust.: The cloud provider trusts the token because it can verify the CI's signature and the claims it carries (which repo, which branch, which workflow). The trust is in the identity, not in possession of a secret. This is the same model OAuth uses for end users, applied to CI.
- Native support in major CI providers.: GitHub Actions, GitLab CI, CircleCI, and Buildkite all ship OIDC integration with AWS, GCP, Azure, and HashiCorp Vault. The implementation is configuration, not custom code. Adopting it for new pipelines is straightforward; migrating existing ones is a multi-week project worth doing.
- Per-claim authorization.: The cloud-side trust policy can grant different permissions based on the CI's claims. "Pipelines from main branch can deploy to prod; pipelines from feature branches can only deploy to dev." This makes the permission decision precise and auditable.
OIDC for CI is the security upgrade that pays back fastest. Long-lived secrets in CI are the largest credential-management liability most organizations have. Replacing them with OIDC eliminates the liability entirely.
Audit
The third leg of the CI permission model is audit: knowing, after the fact, what each pipeline actually did. The audit trail is what makes incident response, compliance, and security review work.
- What CI did, recorded.: Every action a CI pipeline takes (cloud API calls, deploys, registry pushes, secret reads) is logged with the pipeline ID, the commit SHA, and the timestamp. The log is durable, queryable, and retained for the period required by compliance.
- Reviewed periodically.: Security or platform team reviews the CI audit trail on a cadence (monthly is common). Anomalies (a pipeline reading from a secret it has not touched in months, a deploy from an unexpected branch, a credential being used outside business hours) are investigated.
- Compliance friendly.: SOC 2, ISO 27001, PCI DSS all require change-management and access-control evidence. The CI audit log is the literal answer to controls like CC6.1 (logical access) and CC8.1 (change management). Auditors look at it once and move on.
- Forensic ready.: When something goes wrong (a bad deploy, a leaked credential, a suspicious pipeline run), the audit log is the foundation of the investigation. Without it, the team is reconstructing from CI logs and chat history. With it, the timeline is queryable in minutes.
- Tamper-evident retention.: The audit log is written to a destination CI cannot modify after the fact. Append-only storage, signatures, or external SIEM aggregation. The CI cannot quietly rewrite its own history; that is the property that makes the log meaningful.
Least privilege, OIDC, and audit together produce a CI permission model that is defensible against the threats CI realistically faces: token theft, supply-chain compromise, malicious commits, accidental misconfigurations. Nova AI Ops integrates with CI provider audit streams, watches for anomalous CI behavior in real time, and surfaces the credential-usage pattern across pipelines so the security team has visibility without having to interrogate every team's CI separately.