The anatomy of the attack

On March 19, 2026, Aqua Security's Trivy — one of the most widely used vulnerability scanners in the world — was compromised. Attackers injected credential-harvesting logic directly into the official release binary.

The payload was sophisticated: scans appeared to complete and pass normally. The credential exfiltration ran silently alongside legitimate functionality. Teams had no indication anything was wrong.

The attack didn't need to find a vulnerability in your code. It exploited the fact that your CI/CD pipeline runs tools with access to your environment — and your API keys live in that environment as plaintext strings.

This is the supply chain attack model that makes traditional secrets management insufficient: if the key exists as a plaintext string anywhere in your runtime environment, a compromised tool can find and exfiltrate it.

ENTRY POINT

Attacker compromises Trivy release

Exploits mutable Git tags and self-declared commit identity to inject malware into official v0.69.4 release binary.

PROPAGATION

GitHub Actions pick up the payload

Both trivy-action and setup-trivy were affected. Pipelines using compromised releases or mutable tags could run the malicious payload through trusted automation paths.

EXFILTRATION

Credentials harvested from runtime environment

The malicious payload accessed plaintext credentials from affected runtime environments, including values exposed after a secret-retrieval step. Harvested credentials were sent to attacker infrastructure.

WHERE VAULTPROOF REDUCES EXPOSURE

Raw provider key stays out of the runner

With VaultProof's provider-proxy flow, the CI/CD job uses a scoped project value instead of the raw provider key. Encrypted shares remain in VaultProof storage rather than the runner environment.

Why secret retrieval
left a runtime gap

Many common secret-retrieval workflows store a key encrypted, then expose its plaintext value to the process that needs it. When a CI/CD job retrieves a credential into an environment variable or process memory, other compromised code running with that access may be able to read it.

This is intentional. It's how these tools are designed. They protect the key at rest — not in use.

ci-pipeline.yml (simplified)
$ doppler run -- npm test
# Doppler retrieves OPENAI_API_KEY from vault...
# Sets it as environment variable...
export OPENAI_API_KEY=sk-proj-Ab3xK9mNpQ...

# ↑ Plaintext. In the environment.
# Every tool this pipeline runs can read it.
# Including a compromised Trivy binary.

Running tests...
Running Trivy scan...
OPENAI_API_KEY exfiltrated to attacker infrastructure
✓ Trivy scan passed (0 vulnerabilities found)

The Trivy malware did not need to find an application vulnerability. It abused the runtime access already available to a trusted build tool and read credentials that affected jobs had exposed to that environment.

What reduces
this exposure

A strong defense against this credential-harvesting path is to ensure the raw provider credential does not enter the CI/CD runner environment. That control still belongs alongside pinned dependencies, least privilege, short-lived cloud identity, monitoring, and rotation.

VaultProof uses split-key storage and a provider-compatible proxy. The CI/CD job receives a scoped VaultProof project value and routed base URL instead of the original provider key; encrypted shares remain inside the VaultProof service boundary.

🔑

Key Registration

Your API key is split before upload, and both stored shares are protected as separate authenticated ciphertexts.

🛡️

Runtime Request

Your app requests the API call. VaultProof proxy collects shares, reconstructs key in memory for milliseconds only.

Call Complete

API call succeeds. Reconstructed key is zeroed from memory. No plaintext key was ever in your app environment.

A compromised tool in this runner would not find the original provider key in the application environment. That removes one credential-harvesting path, while dependency integrity, runner isolation, short-lived identity, monitoring, and rotation remain necessary.