Supply-Chain Attacks Turn Security and DevSecOps Tools into Credential-Theft Paths

· Original article ↗

Summary

An analysis of supply-chain compromises affecting XZ Utils, GitHub Actions dependencies, Trivy, and LiteLLM describes how attackers abused trusted tools and release paths to steal credentials, and outlines defensive measures.

Key points

  • The XZ Utils backdoor used malicious binary test fixtures and a build-time injection mechanism; it was discovered after an engineer noticed unusual SSH authentication latency.
  • A compromised reviewdog dependency propagated through GitHub Actions to tj-actions/changed-files, exposing CI runner memory to credential scraping across more than 23,000 repositories.
  • Attackers retained an Aqua Security bot token after credential rotation, then poisoned Trivy action tags and a release; payloads targeted runner memory or files containing credentials.
  • The Trivy payload used Internet Computer infrastructure for C2 and a GitHub release as a fallback exfiltration path, complicating conventional takedown responses.
  • Malicious LiteLLM PyPI versions used a Python .pth file to run automatically when Python started, collecting credentials and Kubernetes secrets; a process-forking bug caused crashes that helped expose it.
  • The article recommends pinning GitHub Actions to full commit SHAs, auditing and rotating bot tokens, monitoring action entrypoint changes, reviewing pull_request_target workflows, and checking package provenance.
  • It says the Trivy and LiteLLM incidents shared persistence naming and encryption patterns, but leaves open whether they involved the same actor or a shared toolkit.

Article Details

Attack Vectors
  • XZ Utils 5.6.0 and 5.6.1 contained a backdoor introduced through binary test files that injected a precompiled object into the liblzma build.
  • The XZ operation used contributor personas to build trust and pressure the maintainer before malicious code was introduced.
  • A compromised reviewdog action propagated through transitive GitHub Actions dependencies to tj-actions/changed-files, where a Python payload scraped CI runner process memory for secrets.
  • Aqua Security's Trivy workflows were exploited through pull_request_target; after an incomplete credential rotation, retained aqua-bot credentials were used to repoint action tags and publish a malicious Trivy release.
  • The Trivy payload harvested credentials from runner memory or filesystem locations, then used ICP-hosted C2 and a GitHub release asset as an exfiltration path.
  • Malicious LiteLLM versions were uploaded directly to PyPI using compromised maintainer credentials, bypassing the GitHub release pipeline. A .pth file executed payload code when Python started.
  • The LiteLLM payload collected credentials and Kubernetes secrets, created a privileged pod mounting the host filesystem, and installed persistence as a systemd user service.
Defensive Notes
  • Pin GitHub Actions to full commit SHAs rather than mutable version tags.
  • After a CI/CD compromise, audit and rotate bot and service-account tokens, including tokens with release or tag write permissions.
  • Monitor downloaded GitHub Action entrypoint sizes against per-action, per-SHA baselines and investigate significant deviations.
  • Map transitive Action dependencies and review their write permissions and ability to execute shell commands.
  • Block and log CI runner egress to blockchain domains such as *.icp0.io, as recommended by the article.
  • Audit workflows using pull_request_target and apply least-privilege secret scopes; replace the trigger with pull_request when its use is not justified.
  • Verify commit identity using commit SHAs and provenance or transparency records rather than relying on GitHub UI timestamps.
  • Check package versions against corresponding GitHub releases or signed provenance, and treat mismatches as unverified.
  • Treat files matching ~/.config/sysmon*.py on developer machines or CI runners as requiring immediate triage, as recommended by the article.

Indicators of compromise

TypeIndicatorContext
DOMAINscan[.]aquasecurtiy[.]orgTyposquatted domain identified as the Trivy incident's primary exfiltration destination.
URLhxxps[:]//models[.]litellm[.]cloud/Typosquatted URL used to receive the encrypted LiteLLM credential bundle.
URLhxxps[:]//tdtqy-oyaaa-aaaae-af2dq-cai[.]raw[.]icp0[.]ioPrimary C2 URL polled by the malicious Trivy binary.

MITRE ATT&CK

T1027 · Obfuscated Files or InformationThe XZ payload was stored in binary test fixtures and de-obfuscated at build time using tr.T1036 · MasqueradingThe XZ operation used credible fake contributor identities to author commits and pressure the maintainer.T1036.005 · Match Legitimate Resource Name or LocationThe Trivy and LiteLLM payloads used sysmon.py naming to resemble legitimate system-monitoring artifacts.T1041 · Exfiltration Over C2 ChannelThe Trivy and LiteLLM payloads sent encrypted data to their C2 destinations.T1048 · Exfiltration Over Alternative ProtocolThe tj-actions incident exfiltrated secrets by printing them to public CI workflow logs.T1059.006 · PythonA malicious Python script ran on CI runners and scraped process memory in the tj-actions incident.T1098 · Account ManipulationAn unrevoked aqua-bot service-account token retained release-signing access after credential rotation.T1102 · Web ServiceThe malicious Trivy binary polled an ICP blockchain-hosted endpoint for C2.T1195.001 · Compromise Software Dependencies and Development ToolsMalicious code entered software dependencies or development tools, including the XZ Utils build and poisoned reviewdog action.T1195.002 · Compromise Software Supply ChainThe Trivy incident exploited a pull_request_target workflow and force-pushed action tags to malicious code.T1199 · Trusted RelationshipA poisoned reviewdog action propagated through transitive dependencies to tj-actions and downstream repositories.T1528 · Steal Application Access TokenThe tj-actions payload extracted GitHub Actions runner tokens and repository secrets from process memory.T1543.001 · Launch AgentThe LiteLLM payload installed sysmon.service as a persistent systemd user service.T1552 · Unsecured CredentialsTrivy and LiteLLM payloads searched filesystems for SSH keys, cloud credentials, Kubernetes secrets, and other sensitive data.T1552.001 · Credentials In FilesThe tj-actions payload read /proc/{PID}/mem and searched runner memory for GitHub secret structures.T1554 · Compromise Host Software BinaryA backdoored XZ Utils binary was distributed through upstream release channels.T1556 · Modify Authentication ProcessThe XZ implant hooked RSA_public_decrypt resolution and weakened SSH public-key authentication.T1567.001 · Exfiltration to Code RepositoryThe Trivy payload uploaded an encrypted credential bundle as a release asset in an attacker-created GitHub repository.T1585.001 · Social Media AccountsThe XZ operation used fake contributor personas to establish accounts and pressure the maintainer.T1611 · Escape to HostThe LiteLLM payload created a privileged Kubernetes pod in kube-system that mounted the host filesystem.

CVE

People

Threat Actors

Vendors

Products

GitHub ActionsStep 4 — tj-actions/changed-files is one of the most widely used GitHub Actions in existence — it detects which files changed in a PR. It internally depends on eslint-changed-files, so it too pulled in the poison.liblzmafrom any scanner in common use. The resulting bash script injected a precompiled object file into the liblzma build stage.​LiteLLMCase Study IV — litellm v1.82.8 (PyPI, March 24, 2026): The .pth Auto-Execution EscalationPyPICase Study IV — litellm v1.82.8 (PyPI, March 24, 2026): The .pth Auto-Execution Escalationreviewdog/action-setupStep 1 — reviewdog/action-setup is a utility action — it installs the reviewdog linting tool onto the CI runner. It's a building block that other reviewdog actions depend on.reviewdog/action-typosStep 2 — reviewdog/action-typos (and other reviewdog actions) call action-setup first to install the tool before doing their own work. So when action-setup was poisoned, every action that used it inherited the malicioussetup-trivyretained credentials, the attacker force-pushed 76 of 77 version tags in trivy-action and all 7 in setup-trivy to a malicious commit, while simultaneously publishing trivy v0.69.4 through the compromised releasetj-actions/changed-filesOn March 14, 2025, tj-actions/changed-files, embedded in over 23,000 repositories, was found executing a malicious Python script on CI runners. Initial reporting framed this as a single-action compromise.tj-actions/eslint-changed-filesStep 3 — tj-actions/eslint-changed-files uses reviewdog actions internally to lint changed files, so it pulled in the poisoned action-setup transitively.TrivyCase Study III — Aqua Security / Trivy (March 2026): The Blockchain-Backed, Multi-Stage Infostealertrivy-actionUsing aqua-bot's retained credentials, the attacker force-pushed 76 of 77 version tags in trivy-action and all 7 in setup-trivy to a malicious commit, while simultaneously publishing trivy v0.69.4 through theXZ UtilsCase Study I — XZ Utils (CVE-2024-3094): The Two-Year Patience Operation

Tools

Industries

Related Articles