Your CI pipeline is the new perimeter
Attackers have stopped knocking on the front door of production. They go through the build system instead, because it holds every secret and deploys everything. Six controls that close most of the gap.
Ask an engineering team where their most sensitive system is and they will point at the production database. Ask an attacker and they will point at the CI runner.
The build pipeline holds deploy keys, cloud credentials, package registry tokens and signing keys. It runs code from pull requests, third-party actions and thousands of transitive dependencies. And it has write access to production by design. That combination makes it the most valuable target most companies own, and often the least reviewed.
Where pipelines actually break
The incidents we see rarely involve exotic techniques. They cluster around a few patterns:
- Long-lived cloud keys stored as CI secrets, readable by any workflow and often by any branch.
- Workflows triggered by untrusted pull requests that still have access to secrets.
- Third-party actions pinned to a mutable tag like
v3, which the author, or someone who compromised the author, can change at any time. - Dependencies resolved fresh on every build, so a malicious package version published at 2 a.m. ships at 9 a.m.
Six controls that close most of the gap
1. Replace stored cloud keys with short-lived federation
Most CI platforms can exchange a signed identity token for temporary cloud credentials using OpenID Connect. No static key exists to leak. Scope the trust policy to a specific repository and branch, not to your whole organisation.
2. Pin actions and images by digest
A tag is a promise; a commit hash is a fact.
# instead of
uses: some-org/setup-tool@v3
# pin the exact commit
uses: some-org/setup-tool@3f1c2a9e4b7d...
Use a bot to propose updates so pinning does not turn into never updating.
3. Separate untrusted builds from privileged ones
Pull requests from forks should build and test with no secrets at all. Deployment jobs should run only on protected branches, after review, in a separate environment that requires approval.
4. Lock dependencies and verify them
Commit lockfiles, install with the frozen-lockfile flag your package manager provides, and run a dependency check that fails the build on known-malicious packages, not just known vulnerabilities.
5. Give every job the least permission it needs
Default workflow tokens are often far more powerful than any single job requires. Set the default to read-only and grant write access per job, explicitly.
6. Make the pipeline observable
Ship CI audit logs to the same place as your other security logs. Alert on new self-hosted runners, changes to branch protection, new deploy keys and secrets read outside the expected workflow.
Where to start on Monday
If you do one thing this week, list every secret your CI platform stores and ask, for each one, whether it could be a short-lived credential instead. In most environments the answer is yes for the most dangerous ones, and removing a static cloud admin key from CI does more for your risk than almost any scanner you could add.
A short consultation: we walk your surface and show where to start.