Note: The GitLab product did not use any of the compromised package versions mentioned in this post.In the span of 12 days, four separate supply chain attacks revealed that continuous integration and continuous delivery (CI/CD) pipelines have become a high-value target for sophisticated threat actors.Between March 19 and March 31, 2026, threat actors compromised:an open-source security scanner (Trivy)an infrastructure-as-code (IaC) security scanner (Checkmarx KICS)an AI model gateway (LiteLLM)a JavaScript HTTP client (axios)Each attack shared the same surface: the build pipeline.

This article shows what happened, why pipelines can be uniquely vulnerable, and how centralized policy enforcement with GitLab — using policies defined below — can block, detect, and contain these classes of attack before they reach production.Trusted by millions, compromised in minutesHere is the timeline of the supply chain attacks:March 19: Trivy security scanner becomes an attack vectorTrivy is one of the most widely used open-source vulnerability scanners in the world. It is the tool teams run inside their pipelines to find vulnerabilities.On March 19, a threat actor group known as TeamPCP used compromised credentials to force-push malicious code into 76 of 77 version tags of the aquasecurity/trivy-action GitHub Action and all 7 tags of aquasecurity/setup-trivy. Simultaneously, they published a trojanized Trivy binary (v0.69.4) to official distribution channels. The payload was credential-stealing malware that harvested environment variables, cloud tokens, SSH keys, and CI/CD secrets from every pipeline that ran a Trivy scan.The incident was assigned CVE-2026-33634 with a CVSS score of 9.4. The Cybersecurity and Infrastructure Security Agency (CISA) added it to the Known Exploited Vulnerabilities catalog within days.March 23: Checkmarx KICS falls nextUsing stolen credentials, TeamPCP pivoted to Checkmarx’s open-source KICS (Keeping Infrastructure as Code Secure) project. They compromised the ast-github-action and kics-github-action GitHub Actions, injecting the same credential-stealing malware. Between 12:58 and 16:50 UTC on March 23, any CI/CD pipeline referencing these actions was silently exfiltrating sensitive data, such as API keys, database passwords, cloud access tokens, SSH keys, and service account credentials.March 24: LiteLLM compromised via stolen Trivy credentialsLiteLLM, an LLM API proxy with 95 million monthly downloads, was the next target. TeamPCP published backdoored versions (1.82.7 and 1.82.8) to PyPI using credentials harvested from LiteLLM’s own CI/CD pipeline, which used Trivy for scanning.The malware targeting Version 1.82.7 used a base64-encoded payload injected directly into litellm/proxy/proxy_server.py that executed at import time. The version targeting 1.82.8 used a .pth file, a Python mechanism that executes automatically during interpreter startup. Simply installing LiteLLM was enough to trigger the payload. Attackers encrypted the stolen data (SSH keys, cloud tokens, .env files, cryptocurrency wallets) and exfiltrated it to models.litellm.cloud, a lookalike domain.March 31: Source code for AI coding assistant leaked via simple packaging mistakeWhile the TeamPCP campaign was still unfolding, a software company shipped an npm package containing a 59.8 MB source map file — one that referenced its AI coding assistant's complete, unminified TypeScript source code, hosted in the company's own Cloudflare R2 bucket.The leak exposed 1,900 TypeScript files, 512,000+ lines of code, 44 hidden feature flags, unreleased model codenames, and the full system prompt for anyone who knew where to look. As engineer Gabriel Anhaia explained, “A single misconfigured .npmignore or files field in package.json can expose everything.”March 31: axios and another trojan in the supply chainThat same day, a sophisticated campaign targeted the axios npm package, a JavaScript HTTP client with over 100 million weekly downloads.A compromised maintainer account published backdoored versions (1.14.1 and 0.30.4). It injected a malicious dependency ([email protected]) that deployed a Remote Access Trojan capable of running on macOS, Windows, and Linux. Both release branches were hit within 39 minutes, with the malware designed to self-destruct after execution.The patterns behind these attacksAcross these five incidents, three distinct attack patterns emerge, and all of them exploit the implicit trust that CI/CD pipelines place in their inputs.Pattern 1: Poisoned tools and actionsThe TeamPCP campaign exploited a fundamental assumption: that the security tools running inside your pipeline are themselves trustworthy. When a GitHub Action tag or a PyPI package version resolves to malicious code, the pipeline executes it with full access to environment secrets, cloud credentials, and deployment tokens. There is no verification step because the pipeline trusts the tag.A recommended pipeline-level control: Pin tools and actions to immutable references (commit SHAs or image digests) rather than mutable version tags. Where pinning is not practical, verify the integrity of tools and dependencies against known-good checksums or signatures. Block execution if verification fails.Pattern 2: Packaging misconfigurations that leak IPA misconfigured build pipeline shipped debugging artifacts straight into the production package. A misconfigured .npmignore or files field in package.json is all it takes. A pre-publish validation step should catch this every time.A recommended pipeline-level control: Before any package is published, run automated checks that validate the package contents against an allowlist, flag unexpected files (source maps, internal configs, .env files), and block the publish step if the checks fail.Pattern 3: Vulnerabilities in transitive dependenciesThe axios attack targeted not just direct users of axios, but anyone whose dependency tree resolved to the compromised version. A single poisoned dependency in a lockfile can thus propagate through an entire organization’s build infrastructure.A recommended pipeline-level control: Compare dependency checksums against known-good lockfile state. Detect unexpected new dependencies or version changes. Block builds that introduce unverified packages.How GitLab Pipeline Execution Policies address each attack patternGitLab Pipeline Execution Policies (PEPs) enable security and platform teams to inject mandatory CI/CD jobs into every pipeline across an organization, regardless of what a developer defines in their .gitlab-ci.yml. Jobs defined in PEPs cannot be skipped, even with [skip ci] or [no_pipeline] directives. Jobs can be executed in reserved stages (.pipeline-policy-pre and .pipeline-policy-post) that bookend the developer’s pipeline.We have published ready-to-use pipeline execution policies for all three patterns as an open-source project: Supply Chain Policies. These policies are independently deployable, and each one ships with violation samples that you can use to test them. Here is how each one works.Use case 1: Prevent accidental exposure in package publishingProblem: A source map file ended up in the npm package of an AI coding tool after the build pipeline skipped publish-time validation.PEP approach: We built an open-source Pipeline Execution Policy for exactly this class of error: Artifact Hygiene.The policy injects .pipeline-policy-pre jobs that auto-detect the artifact type (npm package, Docker image, or Helm chart) and inspect the contents before any publish step runs. For npm packages, it performs three checks:File pattern blocklist. Scans npm pack output for source maps (.map), test directories, build configs, IDE settings, and src/ directories.Package size gate. Blocks packages exceeding 50 MB, like the 59.8 MB package that leaked the AI tool.sourceMappingURL scan. Detects external URLs (the R2 bucket pattern that exposed a major AI company’s source), inline data: URIs, and local file references embedded in JavaScript bundles.When violations are found, the pipeline fails with a clear report in the failed CI job logs: =============================================