Unit 10: Packages, signatures and patching · Lesson 5 of 5 · 22 min

Case file: when the security scanner is the attack

A poisoned release of a popular scanner stole CI secrets. Verify downloads and pin what your pipelines run.

mission

You are
You are reviewing the CI tools the shop uses.
Situation
Two releases of a scanner and the CI workflows that run it are in /srv/cases/ci-tools, with the vendor's advisory.
Goal
Find the bad download and every workflow that would pull the tampered action.
Hand in
Which file to delete and which workflows to pin.

case file

Trivy Security Scanner Compromise (TeamPCP)

Aqua Security (Trivy), with follow-on Checkmarx KICS and LiteLLM · 2026

On March 19, 2026, attackers known as TeamPCP pushed a backdoored Trivy release (v0.69.4) and force-pushed 75 of 76 trivy-action tags to malicious versions that harvested CI secrets from runner memory and developer machines (tracked as CVE-2026-33634). Wiz reported the attacker retained access after an earlier incident was incompletely contained, including via a compromised bot service account. Using stolen secrets, the campaign spread to Checkmarx KICS GitHub Actions on March 23 and to malicious LiteLLM PyPI releases (1.82.7 and 1.82.8) on March 24.

What went wrong

Incompletely remediated earlier compromise left attacker access to project credentials and a privileged bot account; consumers referenced Actions by mutable tags and ran the scanner with broad secrets available.

What would have stopped it

  • After any CI/CD incident, rotate every credential the attacker could have reached, including bot and service accounts, and verify containment.
  • Pin Actions to commit SHAs and verify release signatures/checksums for downloaded tools and container images.
  • Run security scanners with minimal secrets and restricted egress, since they execute inside sensitive pipelines.
  • Use short-lived OIDC credentials in CI instead of long-lived tokens.

What defenders could have seen

  • New repositories named 'tpcp-docs' in your GitHub organization.
  • Outbound connections from runners to typosquatted or tunnel domains during a scan step.
  • Unexpected systemd user services appearing on developer workstations.

sourceswiz.ioarcticwolf.com

Tags move, commits do not

  1. @v1Points wherever the owner moves it
  2. Tag movedTo a malicious commit
  3. Your pipelineRuns it with your secrets
  4. @full-shaAlways the code you reviewed
01

Read the advisory

learner@root-lab
cat advisory.txt
Advisory 2026-03-20: release 0.69.4 of the scanner was published by an attacker.
Known bad SHA-256:
7c7a57527c654b17e91d95a5ea833f005f05918ae1daa75499fb2115f529b198  scanner_0.69.4_linux-amd64.tar.gz
Action tags v1 and v1.2 were moved to malicious commits. Pin to a full commit SHA.

you should see A known-bad release and two moved tags.

02

Hash the downloads

learner@root-lab
sha256sum downloads/*
eee1dc81f326acc8e930237b5d2f98d30014e3e62d240c62efcec19970127575  downloads/scanner_0.69.3_linux-amd64.tar.gz
7c7a57527c654b17e91d95a5ea833f005f05918ae1daa75499fb2115f529b198  downloads/scanner_0.69.4_linux-amd64.tar.gz
cd downloads && sha256sum -c ../checksums_0.69.3.txt
scanner_0.69.3_linux-amd64.tar.gz: OK

you should see 0.69.3 matches the published checksum. 0.69.4 matches the advisory's bad hash.

03

Find mutable references

A tag can be moved to new code. A full commit SHA cannot.

learner@root-lab
grep -nE 'uses: [^ ]+@v[0-9.]+$' workflows/*.yml
workflows/build.yml:8:      - uses: example-org/scanner-action@v1
workflows/nightly.yml:9:      - uses: actions/checkout@v4
workflows/nightly.yml:10:      - uses: example-org/scanner-action@v1.2

you should see Three references by tag, two of them to the scanner action.

04

Which secrets would they see?

learner@root-lab
grep -n 'secrets\.' workflows/*.yml
workflows/nightly.yml:12:          CLOUD_DEPLOY_KEY: ${{ secrets.CLOUD_DEPLOY_KEY }}
workflows/release.yml:15:          REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}

you should see The nightly scan passes a cloud deploy key to a step that uses a moved tag.

defender tip Give scanning jobs no secrets at all, and pin every action to a reviewed commit SHA.

Referencing an action

By tag
uses: example-org/scanner-action@v1

Whoever moves the tag decides what runs

By commit
uses: example-org/scanner-action@6c3d1b0f...

The code you reviewed, every time

What a defender takes away

  1. 1Verify every download against a published hash.
  2. 2Pin CI actions to full commit SHAs.
  3. 3Security tools get least privilege too.

Questions

0 of 2 solved

Answer each one from what you find on your lab machine.