GitHub Actions Injection Pushes Malicious elementary-data Releases to PyPI and GHCR

· Original article ↗

Summary

A GitHub Actions script-injection flaw let an attacker forge a release of elementary-data 0.23.3, published to PyPI and GHCR with a credential-stealing .pth payload. The team removed the artifacts and released clean 0.23.4.

Key points

  • The article traces the compromise to a comment injected into a vulnerable GitHub Actions workflow, where untrusted comment text was interpolated into a shell command.
  • Using the workflow’s GITHUB_TOKEN, the attacker forged a release commit and dispatched the publishing pipeline without changing the master branch or opening a pull request.
  • The pipeline published elementary-data 0.23.3 to PyPI and pushed a matching multi-architecture image tagged 0.23.3 and latest to ghcr[.]io/elementary-data/elementary.
  • A malicious elementary.pth file ran at Python interpreter startup and contained a multi-stage payload described as harvesting credentials and secrets from developer systems and cloud APIs.
  • The article says the payload packaged collected data and attempted to send it to igotnofriendsonlineorirl-imgonnakmslmao[.]skyhanni[.]cloud; it does not establish that credentials were successfully stolen.
  • The Elementary team removed the malicious package and image and published clean version 0.23.4; the article also describes StepSecurity detection and blocking measures.

Article Details

Attack Vectors
  • An attacker injected a pull-request comment into a GitHub Actions workflow shell command, causing the runner to execute a curl | bash stager with the repository's GITHUB_TOKEN available.
  • The attacker used the workflow access to forge a release commit and dispatch the publishing workflow against an orphan-tagged commit, distributing elementary-data 0.23.3 to PyPI and a compromised container image to GHCR.
  • The malicious elementary.pth file executes when Python starts in an environment where the package is installed.
  • The payload harvested credentials and secrets from local files and cloud APIs, archived the collected data, and sent it to an external C2 endpoint.
Defensive Notes
  • The Elementary team removed elementary-data 0.23.3 from PyPI and the matching malicious GHCR image, then published clean version 0.23.4; the :latest tag was updated to the clean image.
  • Check Python environments and container deployments for the compromised 0.23.3 package and image, including images pulled through an unpinned :latest tag.
  • Pin container images by digest rather than relying on :latest or an unpinned image reference.
  • Harden-Runner can block the reported C2 domain; StepSecurity also reports adding elementary-data 0.23.3 to its Compromised Package Check.
  • The article notes that the PyPI Package Cooldown Check can hold newly published versions for review.

Indicators of compromise

TypeIndicatorContext
DOMAINigotnofriendsonlineorirl-imgonnakmslmao[.]skyhanni[.]cloudC2 and exfiltration domain that received the payload's POST containing harvested credentials and secrets.
SHA25631ecc5939de6d24cf60c50d4ca26cf7a8c322db82a8ce4bd122ebd89cf634255Digest of the compromised elementary-data GHCR image tagged 0.23.3 and latest.
URLhxxps[:]//litter[.]catbox[.]moe/iqesmbhukgd2c7hq.shReported expired URL for the attacker's curl | bash stager.

MITRE ATT&CK

T1005 · Data from Local SystemThe payload collected credentials, keys, configuration files, and other data from local files.T1041 · Exfiltration Over C2 ChannelThe payload sent the collected archive in a POST request to the reported C2 domain.T1059.004 · Unix ShellA pull-request comment was interpolated into a workflow shell command, where the attacker's curl | bash stager executed.T1059.006 · PythonThe elementary.pth payload executes Python code automatically when the interpreter starts.T1071.001 · Web ProtocolsThe payload communicated with its reported C2 endpoint using an HTTP(S) POST request.T1105 · Ingress Tool TransferThe workflow ran a curl | bash stager identified by the article as a URL, consistent with transferring and executing the stager.T1119 · Automated CollectionThe harvester searched across multiple locations, including .env files to depth six and credential files, for collection.T1140 · Deobfuscate/Decode Files or InformationThe payload decodes a base64 wrapper and decrypts two further XOR-with-MD5-keystream layers.T1195.002 · Compromise Software Supply ChainThe attacker compromised the release workflow and used it to publish a trojaned Python package and container image.T1528 · Steal Application Access TokenThe harvester collected application and service tokens, including a gh auth token and Kubernetes ServiceAccount tokens.T1552.001 · Credentials In FilesThe payload searched files such as .git-credentials, cloud credentials, and configuration files for secrets.T1552.004 · Private KeysThe payload collected SSH private keys and other private key material from disk.T1552.005 · Cloud Instance Metadata APIThe payload queried the AWS instance metadata service for role information.T1560.001 · Archive via UtilityThe collected data was compressed into the tar-gzipped archive trin.tar.gz before transmission.

People

Threat Actors

Vendors

Products

Tools

Related Articles