Most CI/CD security controls protect everything around the build. SAST scans code before it runs. SCA checks dependencies in the manifest. Artifact scanners inspect the output after the build completes. None of these tools see what happens during the build itself.
That gap is where software supply chain attacks live. The tj-actions/changed-files compromise backdoored an action used by 23,000 repositories and dumped CI/CD secrets into public workflow logs wherever it ran without exploiting a single vulnerability in application code. The LiteLLM PyPI backdoor planted a credential stealer that ran on every Python startup, not just at install time. The Ultralytics attack used a crafted branch name to run a curl-to-bash payload inside the runner. Every one of these attacks executed inside the build runner, in the space between code commit and artifact output, where conventional security controls are effectively blind.
CI/CD build hardening is the practice of applying security controls inside that space — at runtime, during the build, at the kernel level. This guide covers what it means, how eBPF makes it possible, and why runtime-observed SBOMs and SLSA attestation belong in the same pipeline step.
Key takeaways
- CI/CD build hardening is the practice of enforcing security controls inside the build environment at runtime, not before or after it. It is the only approach that observes what actually executes during a build.
- eBPF (extended Berkeley Packet Filter) enables kernel-level visibility into CI/CD runners without modifying pipelines or installing persistent agents. It observes process execution, network connections, and file access as they occur, in real time.
- Build-time SBOMs generated via runtime observation capture what actually executed during the build, not what the manifest declared. This is the only SBOM method that detects dependencies introduced mid-build by compromised actions or malicious packages.
- SLSA provenance attestation creates a cryptographic chain of custody linking a build artifact to its source commit, build environment, and process. Combined with eBPF-observed build behavior, it provides the strongest possible evidence of artifact integrity.
- Cimon delivers all three capabilities — runtime security, runtime-observed SBOM, and SLSA provenance — in a single GitHub Actions or Azure Pipelines step. Free, open, and operational in under five minutes.
What CI/CD Build Hardening Actually Means
Build hardening is not a new concept. In traditional server security, hardening means reducing attack surface: disabling unnecessary services, enforcing least-privilege, applying kernel security modules. The goal is to constrain what the system can do so that a compromise has limited impact.
Applied to CI/CD, the same principle holds. A hardened build environment constrains what the runner can do during a build: which processes it can execute, which network endpoints it can reach, which files it can read or write. Any deviation from that constrained baseline is a signal and, in prevent mode, a block.
Three categories of attacks target the build environment specifically:
- Exfiltration: stealing secrets, tokens, or credentials from the runner environment. The tj-actions attack, the trivy-action TeamPCP compromise, and the reviewdog incident all targeted runner secrets through different exfiltration paths.
- Tampering: modifying build artifacts, environment variables, or source files mid-build. The Ultralytics attack stole the project’s publishing token and poisoned the build cache, so the released package shipped with a cryptominer.
- Persistence: installing backdoors or modifying package manager configurations so the compromise survives beyond the build. The LiteLLM PyPI backdoor dropped a systemd service that polled an external server for commands and kept running on the host long after the build finished.
Build hardening addresses all three categories by monitoring and constraining runner behavior at the kernel level, where the attack behaviors are visible regardless of how the attacker entered.
The Threat Landscape CI/CD Security Must Address
According to Cimon’s documented threat log, six major supply chain attacks targeted CI/CD build environments between December 2024 and March 2026 alone — trivy-action, LiteLLM, Telnyx, tj-actions, reviewdog, and Ultralytics. Each used a different entry point. Each executed the same categories of attack behavior inside the runner. For the full attack breakdown, see our GitHub Actions supply chain attack guide.
The pattern across all of them confirms the same structural problem: build runners hold privileged access to production secrets, signing keys, and deployment credentials, but receive a fraction of the security scrutiny applied to the production systems those credentials protect.
GitHub Actions runs over 5 million workflows daily. According to Datadog’s 2026 State of DevSecOps report, 38% of organizations run at least one workflow vulnerable to script injection or dangerous triggers. The build environment is simultaneously the highest-value target in the software supply chain and the least monitored point in most organizations’ security programs.
How eBPF Enables Runtime Build Security
Runtime build security needs a place to watch from that sits below the build tools and sees what they actually do. eBPF provides exactly that inside the Linux kernel, which is why it has become the standard way to monitor CI/CD runners.
What eBPF is
eBPF (extended Berkeley Packet Filter) is a Linux kernel technology that allows programs to run safely inside the kernel itself. Originally designed for network packet filtering, it has evolved into one of the most powerful visibility and enforcement mechanisms in modern systems security.
What makes eBPF uniquely suited to CI/CD security is a combination of three properties:
- Kernel-level scope: eBPF programs run inside the kernel and observe every system call, file operation, network event, and process lifecycle event — before userspace sees it.
- Real-time enforcement: unlike tools that read audit logs after the fact, eBPF hooks into kernel operations as they occur. Detection and blocking happen before the operation completes.
- No instrumentation required: eBPF does not require modifying applications, pipelines, or kernel code. It attaches to running kernel functions. For CI/CD runners, this means no pre-installed agent and no persistent infrastructure.
What eBPF sees inside a build runner
Applied to a CI/CD runner, eBPF provides visibility into three categories of behavior that no other tool in the pipeline security stack observes:
- Process execution: every subprocess spawned during the build, including those launched by third-party actions, package managers, and build tools. Cimon builds a complete process tree for each job. A reverse shell spawned by a malicious post-install script appears as an anomalous process execution.
- Network connections: every outbound connection from the runner, tied to the specific process that initiated it. An unexpected curl command exfiltrating base64-encoded secrets to an attacker’s server appears as an unauthorized network call.
- File access: /proc/PID/mem reads that extract in-memory secrets, writes to GITHUB_ENV that inject malicious environment variables, reads of credential files. Each is a specific file operation observable at the kernel level.
Why CI/CD runners need a different eBPF approach than Kubernetes
Most eBPF security tooling targets long-lived Kubernetes workloads: Falco, Tetragon, and similar tools build behavioral baselines over time and detect anomalies in persistent pods. CI/CD runners are fundamentally different. They are ephemeral. A runner spins up for a single build, runs for minutes, and terminates. There is no persistent workload to baseline over time.
Cimon’s implementation accounts for this. Behavioral baselines are established per pipeline, not per host, and hardening rules fire immediately on installation without requiring a learning phase. The ephemeral nature of runners is a design constraint Cimon is built around, not an obstacle to work around.
Cimon’s Two-Phase Build Hardening Model
Turning monitoring into blocking without breaking working pipelines takes a careful order of operations. Cimon handles it in two phases, with a set of always-on rules running underneath both.
Detect mode: learn before you enforce
In detect mode, Cimon observes pipeline behavior without blocking anything. Every process, network connection, and file access is logged and used to build a behavioral security profile for that pipeline. The output is a security report showing exactly what the pipeline does: which processes it spawns, which external endpoints it calls, which files it reads and writes.
Detect mode is the right starting point. It surfaces unexpected behavior without disrupting CI/CD workflows and generates the data needed to configure an accurate prevent mode policy with minimal false positives.
Prevent mode: enforce the baseline
Once a pipeline’s normal behavior is established, Cimon enforces it. Any deviation triggers a block: unauthorized network call dropped, unexpected process killed, prohibited file access denied. The pipeline fails with a security violation rather than completing silently with attacker-controlled behavior running inside it.
Hardening rules: immediate protection without a learning phase
Cimon’s hardening rules run independently of the detect-then-prevent cycle. These are pre-built detections for known attack patterns: /proc/PID/mem reads, GITHUB_ENV injection, reverse shell subprocess patterns, base64 encoding followed by outbound HTTP. Hardening rules fire from the first pipeline run. No baseline required.
Build-Time SBOMs vs. Manifest SBOMs: Why the Method Matters
A software bill of materials is only as accurate as the method used to generate it. Most SBOM tools generate their inventory from one of two sources: package manifests (package.json, requirements.txt, go.mod) or artifact analysis (scanning the compiled output). Both methods miss a category of dependency that supply chain attacks specifically exploit: packages and libraries introduced during the build itself.
What manifest SBOMs miss
Manifest scanning reads what the package manager declared. It does not observe what actually executed. The gap between declared and executed is exactly where supply chain attacks operate:
- A compromised GitHub Action that runs a malicious script downloading additional packages during the build appears in no manifest.
- A PyPI package with a malicious post-install script installs additional payloads that are never declared in requirements.txt.
- Vendored code copied into a repository without package manager tracking is invisible to manifest scanning.
- Statically linked libraries in C/C++ builds are merged into the binary with no package manager record.
An SBOM generated from manifests reflects what the package manager was told. A runtime-observed SBOM reflects what the build actually did.
How Cimon generates runtime-observed SBOMs
Because Cimon’s eBPF monitoring observes every process execution, library load, and package installation during the build, it can produce an SBOM that reflects actual build-time behavior rather than declared dependencies. This is the only SBOM generation method that:
- Captures dynamically fetched dependencies that never appear in any manifest
- Detects packages loaded by compromised actions or malicious post-install scripts
- Reflects the actual runtime dependency set for that specific build, not an approximation from static analysis
- Can flag supply chain compromise in the SBOM itself — an unexpected package that no manifest declared
| Method | What it captures | What it misses | Supply chain attack detection |
|---|---|---|---|
| Manifest scanning (Syft, Grype, etc.) | Declared packages in package.json, requirements.txt, go.mod | Dynamically fetched deps, vendored code, statically linked libs, anything introduced mid-build | No |
| Binary / artifact analysis | Components found in the compiled artifact | Dependencies introduced during build scripts, compromised packages installed then removed | No |
| Build-time observation with eBPF (Cimon) | Everything that actually executes during the build: processes, libraries loaded, packages installed, network calls made | Nothing — it observes the build as it runs | Yes — detects packages loaded that no manifest declared |
SLSA Attestation: Cryptographic Proof of Build Integrity
Knowing a build is clean is one thing. Proving it later to an auditor or a customer is another, and SLSA provenance is the standard way to produce that proof.
What SLSA is and why it matters now
Supply-chain Levels for Software Artifacts (SLSA) is a framework that provides graduated guarantees about build integrity. An SLSA attestation is a signed, machine-verifiable statement that links a build artifact to its source code, build environment, and build process. It creates a cryptographic chain of custody: this binary came from this commit, built by this workflow, in this environment, at this time.
GitHub has been steadily tightening SLSA enforcement through 2025 and into 2026. For public repositories, attestation generation is shifting from opt-in to default behavior. For teams that have not implemented provenance, enforcement is arriving whether they planned for it or not.
Regulatory requirements are accelerating this further. EO 14028 mandates SBOM and provenance for software sold to the US federal government. NIST SSDF requires evidence of supply chain integrity controls. For enterprise software teams, SLSA attestation is moving from best practice to compliance requirement.
SLSA levels in practice
| SLSA level | What it requires | What it prevents | Cimon coverage |
|---|---|---|---|
| Level 1 | Unsigned provenance document describing how the artifact was built | Accidental or undocumented build changes | Cimon generates provenance at Level 1 from first pipeline run |
| Level 2 | Signed provenance from a hosted build platform using OIDC | Tag manipulation, unsigned artifact tampering | Cimon generates signed provenance via GitHub OIDC on hosted runners |
| Level 3 | Build instructions defined outside the repo in isolated reusable workflows | Repository-level compromise of build definitions; most teams fail this without realising it | Cimon’s eBPF observation provides runtime evidence that the build executed as expected, supporting Level 3 audit requirements |
Cimon Attest signs provenance to the SLSA Provenance v1.0 specification. A signed provenance document meets the requirement for SLSA Build Level 2. To reach Level 3, Cimon pairs that signed provenance with its runtime CI/CD monitoring through the Cycode platform, which supplies the build-execution evidence that Level 3 audits ask for.
The hidden complexity most teams encounter at Level 3
SLSA Level 3 requires that build instructions be defined outside the repository in isolated reusable workflows. Most teams implementing SLSA attestation assume they have achieved Level 3 when they have achieved Level 2. The distinction matters because Level 3 is the threshold that would have prevented the repository-level compromise techniques used in the tj-actions and trivy-action attacks.
Cimon’s eBPF-observed build behavior provides runtime evidence that the build executed as expected, supporting Level 3 audit requirements even when full Level 3 workflow isolation is not yet implemented.
How Cimon generates SLSA provenance
Cimon generates signed SLSA provenance attestations as part of its standard pipeline step, using GitHub OIDC to sign the attestation without storing any signing keys in the repository. The provenance record includes the source commit, workflow file, runner environment, triggering event, and artifact digest.
This is generated in the same step that provides runtime security monitoring and SBOM generation. One workflow step. Three compliance artifacts.
What CI/CD Build Hardening Looks Like in Practice
These three capabilities — runtime security, runtime-observed SBOM, and SLSA provenance — are not independent features. They are layers of the same defense. eBPF visibility enables all three: it is the monitoring mechanism that detects attacks, the observation mechanism that generates accurate SBOMs, and the evidence mechanism that makes SLSA provenance trustworthy.
| Capability | What Cimon does | Why it matters |
|---|---|---|
| Runtime security | Monitors process execution, network egress, and file access at the kernel level via eBPF. Blocks deviations from learned baseline and fires hardening rules for known attack patterns. | Stops supply chain attacks at the execution layer regardless of entry point. The only control that sees what runs inside the build. |
| Runtime-observed SBOM | Generates a software bill of materials by observing what actually executes during the build — not what the manifest declares. | Captures dynamically fetched dependencies and packages introduced mid-build. Detects supply chain compromise in the SBOM itself. |
| SLSA provenance attestation | Generates signed SLSA provenance linking the build artifact to its source commit, workflow, runner environment, and build process. | Creates a cryptographic chain of custody for every artifact. Required for EO 14028 compliance and NIST SSDF alignment. |
Adding all three to a pipeline requires a single Cimon step:
- name: Run Cimon
uses: cycodelabs/cimon-action@v1
with:
prevent: false # set to true for prevent mode
hardening: true # enable build-hardening attack detection Getting Started With Cimon
Cimon is free and open source. It runs on GitHub Actions and Azure Pipelines. Getting started takes under five minutes.
- Step 1: Add Cimon as the first step in a workflow that runs in a trusted context or has access to production secrets. Start with detect mode.
- Step 2: Review the security report generated after the first run. Identify the processes, network connections, and file accesses that are part of normal pipeline behavior.
- Step 3: Enable prevent mode once the baseline is validated. Hardening rules are already active from step 1.
- Step 4: Enable SBOM and SLSA generation if required for compliance. Both are output to the pipeline run artifacts.
- Step 5: Connect Cimon to Cycode for organization-wide visibility across all pipelines, centralized policy management, and incident response workflows.
Full configuration documentation is available in the Cimon docs.
The Build Environment Deserves the Same Security Scrutiny as Production
Organizations apply defense-in-depth to production: network controls, endpoint detection, identity management, secrets management, vulnerability scanning. The build environment that produces production software receives a fraction of that scrutiny, despite holding the same credentials and producing the artifacts that production ultimately runs.
Build hardening closes that gap. eBPF makes kernel-level visibility practical for ephemeral CI/CD runners. Runtime-observed SBOMs make supply chain visibility accurate rather than approximate. SLSA provenance makes build integrity verifiable rather than assumed.
Cimon delivers all three. It is the only tool purpose-built for CI/CD build hardening that combines runtime threat detection, accurate SBOM generation, and SLSA provenance in a single step. Get started with Cimon in under five minutes, or connect with the Cycode team to deploy build hardening across your organization.
Frequently Asked Questions
What is the difference between CI/CD build hardening and SAST or SCA?
SAST and SCA operate on code and manifests before the build runs. They catch code-level vulnerabilities and declared dependency risk. CI/CD build hardening operates inside the build runner during execution. It catches attack behaviors that manifest only at runtime: unauthorized network calls, unexpected process execution, credential file reads, environment variable injection. The approaches are complementary, not interchangeable.
In a layered setup, SAST and SCA run on the pull request to catch problems in the code and its declared dependencies, while build hardening runs inside the job to watch what the pipeline actually does. The first two reduce what you ship with known flaws. Build hardening covers the part neither of them can see, which is the live behavior of the build.
Is a runtime-observed SBOM more accurate than a manifest SBOM?
For capturing what actually executed during a specific build, yes. Manifest SBOMs reflect declared dependencies. Runtime-observed SBOMs reflect actual build-time behavior, including dependencies introduced dynamically during the build. For standard dependency tracking in stable, well-managed codebases, manifest SBOMs are often sufficient. For supply chain security and compliance use cases where accuracy and attack detection matter, runtime observation is the more reliable method.
Many teams run both. The manifest scan gives you a fast inventory on every commit, and the runtime SBOM gives you a record of what the build really pulled in. When the two disagree, the gap is usually worth a look.
Does Cimon introduce latency into CI/CD pipelines?
eBPF programs are verified by the Linux kernel before execution and run in a sandboxed context with strict resource limits. The overhead for most pipelines is negligible. Cimon is designed for production-grade CI/CD use, not security research environments.
Detect mode adds no blocking at all, since it only records what the pipeline does and writes a report at the end. Because the agent starts as the first step and watches the job from the side, it does not change how your existing steps run. Most teams leave it on for every build without noticing a slowdown.
What SLSA level does Cimon's provenance meet?
Cimon Attest produces signed provenance that follows the SLSA Provenance v1.0 specification. On a hosted runner, signing it through GitHub OIDC satisfies SLSA Build Level 2. Level 3 also requires an isolated build and provenance that users cannot forge. Cimon supports Level 3 by combining that signed provenance with its runtime monitoring through the Cycode platform, which shows that the build ran the way it was supposed to.
You can check any attestation later with the cimon attest verify command, which confirms that the artifact matches its signed provenance and was built from the source you expect. That lets a team downstream trust the build without having to run it again.
How does Cimon integrate with the Cycode platform?
Cimon can run as a standalone tool or connect to the Cycode platform for organization-wide capabilities: visibility across all pipeline security reports, centralized allow-list management, remote policy configuration, incident response workflows when violations occur, and integration with broader supply chain security posture management. The standalone version is fully functional for individual pipelines and teams.
Connecting means generating an API key in Cycode, which gives you a client ID and a secret, then storing them as pipeline secrets that the action reads at runtime. Once connected, reports from every pipeline land in one place instead of staying inside individual job summaries.
Does Cimon work on Azure Pipelines as well as GitHub Actions?
Yes. Cimon is available as both a GitHub Action and an Azure Pipelines task. The eBPF-based monitoring works on any Linux runner regardless of the CI/CD platform provider.
It also runs on Jenkins, GitLab CI, Buildkite, and Harness, and there is a CLI for environments that do not have a native integration yet. Since the monitoring happens in the kernel, the same detections apply no matter which platform schedules the job.
