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

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
| Type | Indicator | Context |
|---|---|---|
| DOMAIN | igotnofriendsonlineorirl-imgonnakmslmao[.]skyhanni[.]cloud | C2 and exfiltration domain that received the payload's POST containing harvested credentials and secrets. |
| SHA256 | 31ecc5939de6d24cf60c50d4ca26cf7a8c322db82a8ce4bd122ebd89cf634255 | Digest of the compromised elementary-data GHCR image tagged 0.23.3 and latest. |
| URL | hxxps[:]//litter[.]catbox[.]moe/iqesmbhukgd2c7hq.sh | Reported 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
elementary-dataA malicious version of elementary-data (0.23.3) was published to PyPI and is, at the time of writing, still listed as the latest release. elementary-data is a widely deployed Python package for dbt data observability.GitHub ActionsThe attacker exploited a script injection vulnerability in one of the project's own GitHub Actions workflows, then used the workflow's GITHUB_TOKEN to forge a signed release commit and dispatch the legitimate publishingGitHub Container RegistryThe same release run also pushed a multi-arch container image to GitHub Container Registry at ghcr.io/elementary-data/elementary, tagged both 0.23.3 and latest. Every unpinned docker pullPyPIA malicious version of elementary-data (0.23.3) was published to PyPI and is, at the time of writing, still listed as the latest release. elementary-data is a widely deployed Python package for dbt data observability.
Tools
Compromised Package Checkthe relevant indicators are pushed to downstream protections (Harden-Runner global block list, Compromised Package Check, Developer MDM, etc.) so they take effect across every workflow without any customerDeveloper MDMare pushed to downstream protections (Harden-Runner global block list, Compromised Package Check, Developer MDM, etc.) so they take effect across every workflow without any customer configuration change.harden-runnerand developer-machine inventory and the relevant indicators are pushed to downstream protections (Harden-Runner global block list, Compromised Package Check, Developer MDM, etc.) so they take effect across everyPyPI Package Cooldown Checkintroduce a known-malicious version. elementary-data==0.23.3 has been added to the list. The PyPI Package Cooldown Check would also have flagged a PR that adopted 0.23.3 for being too newly published to trust,
