Security
Your app is low risk. Your build pipeline is not.
If your software is internal, narrow or unexciting, it is reasonable to put security low on the list. Supply chain attacks do not check what your app does. They go after the pipeline and the packages every app shares.
The reasoning is sound, up to a point
We hear it often, and it usually comes from a sensible place. The app is an internal dashboard, a data pipeline, or a small service with a handful of users. It holds nothing an attacker wants. Security budget goes to the customer-facing product first.
That logic holds for the application. It does not hold for how the application is built. Every team, whatever it ships, has a CI pipeline with credentials in it and a dependency tree it did not write. Those are worth attacking because they are shared, and a compromise there reaches everything else those credentials can touch: your registries, your cloud accounts, and your other repositories.
Attacks that did not care what the app did
None of these incidents targeted a particular kind of application. Each one reached teams through a tool or package they used to build software.
tj-actions/changed-files, 2025
A widely used GitHub Action that detects changed files was compromised. According to CISA, malicious versions were live between March 12 and March 15, 2025, and the compromise exposed secrets including access keys, GitHub personal access tokens, npm tokens and private RSA keys. Wiz reported that the code dumped CI runner memory, so on public repositories the secrets ended up in workflow logs. Workflows that referenced the action by a version tag ran the malicious code, whatever the repository contained.
Shai-Hulud npm worm, 2025
In September 2025, CISA warned of a self-replicating worm that had compromised more than 500 npm packages. It harvested GitHub personal access tokens and cloud API keys for AWS, Google Cloud and Azure. Palo Alto Networks Unit 42 described how it used stolen npm tokens to publish infected versions of the victim's other packages, and how a later wave ran during pre-install, which widened its reach into CI/CD pipelines.
Shai-Hulud and other supply chain attacks
How the Shai-Hulud npm worm stole credentials on install and used them to publish more compromised packages, with the earlier attacks it follows.
Petteri Pulkkinen and Erika Marttinen at Kubernetes Community Days Helsinki 2026, 4:30 to 7:57 of SBOMbastic: Getting Ready for Upcoming EU Cybersecurity Regulation in Software Supply Chains.
Codecov Bash Uploader, 2021
An attacker extracted a credential through an error in Codecov's Docker image build process and modified the Bash Uploader script that many teams ran in CI. From January 31 to April 1, 2021, the altered script could send environment variables, including credentials, tokens and keys available in the CI environment, to a third party. It was found when a customer noticed the script's checksum did not match.
xz utils, 2024
Malicious code was embedded in XZ Utils versions 5.6.0 and 5.6.1, a data compression library that may be present in Linux distributions. CISA advised downgrading to an uncompromised version such as 5.4.6 and hunting for malicious activity. A compression library is about as unglamorous as a dependency gets, and it was still a target.
event-stream, 2018
A person posing as a helpful maintainer took over the popular npm package event-stream and added a malicious dependency, flatmap-stream, in version 3.3.6. The npm team reported that the payload targeted one specific application, the Copay bitcoin wallet. Everyone else who installed event-stream got the malicious code too.
What these incidents have in common
- They happened at build time or install time. The malicious code ran on developer machines and CI runners, not in the production app.
- They went after credentials. Tokens and keys in the pipeline were the prize, because they open doors beyond the project being built.
- They arrived through trusted names. A familiar action, a familiar package, a familiar script. Nobody chose to install malware.
- The first question afterwards was the same. Did any of our builds pull the bad version, and what could it reach? Teams without a record of what each build used had to reconstruct it.
What minimal effort looks like
You do not need a security team to cover the basics. Most of the advice from GitHub and CISA fits in a short list:
- Pin third-party GitHub Actions to a full commit SHA rather than a tag, so a moved tag cannot change what runs.
- Commit lockfiles and pin dependency versions to known good releases.
- Give CI tokens the narrowest permissions that work, and rotate them when an incident touches something you use.
- Require phishing-resistant multifactor authentication on developer and publishing accounts.
- Keep a record of what each build installed, so that you can answer "were we affected?" from data rather than memory.
The first four are configuration. The fifth is the one most small teams skip, because it takes tooling.
Where CRACI fits with little effort
CRACI covers the record keeping and adds a network boundary, without asking you to change your app or your workflows.
- One line per job. Change
runs-ontocraci. Your GitHub Actions workflows stay as they are, and runs still appear in GitHub. - An SBOM from every build. CRACI records the packages each job actually pulls, including packages restored from caches, and exports the result in CycloneDX or SPDX.
- A network trace per job. When an incident is announced, you can check which builds pulled the affected package and where each job connected.
- An egress policy you can switch to default deny. Allow the package sources a job needs, and a compromised step has fewer places to send what it finds. Policies fail closed, and violations trigger an email alert.
- Continuous re-evaluation. Monitored SBOMs are checked again as new vulnerabilities are published, so an old build does not stay "clean" just because nobody looked.
To be clear about the limits: an egress policy would not have stopped the tj-actions compromise from printing secrets into a public log, and no tool undoes a leaked token. Pinning and rotation still matter. What CRACI changes is how quickly you can answer whether you were exposed, and how far a compromised step can reach.
Getting a first workflow running takes installing the GitHub App and
changing one line to runs-on: craci.
What it costs
The Pro plan is €30 per month until the end of 2026. It includes up to 20 users, one actively monitored SBOM and 10,000 build minutes. See pricing for the full terms. Eligible startups can apply to the startup program for a minimum of 100k free build minutes and hands-on onboarding.
If you sell software in the EU, it is also worth checking whether the Cyber Resilience Act applies to you. Our guide to the CRA explains the scope and the deadlines.
See what your build actually pulls in
Book a demo and run one of your workflows on CRACI. You get an SBOM and a network trace for the job, with no change to your app.
Book a demo