Elementary-data’s bad release: quick triage for Python teams

Chainguard says its customers were not impacted, but anyone who pulled elementary-data 0.23.3 from PyPI (or a related Docker Hub image) should investigate

2026-05-08 GIGATAP Team #security
#supply-chain#pypi#python

Elementary-data’s PyPI compromise: what we know, who’s exposed, what to check

Chainguard says its customers were not impacted by a recent compromise of the elementary-data Python package on PyPI, but teams that pulled the malicious release directly from PyPI (or a related container from Docker Hub) should investigate.

What happened (as reported)#

According to Chainguard, a compromised version of the elementary-data package was published to the Python Package Index (PyPI) on April 24, 2026. Chainguard describes elementary-data as a dbt-native data observability tool used for data quality monitoring.

The compromised release was version 0.23.3. Chainguard reports that this version added a single additional file containing obfuscated Python code designed to execute when the package is imported. In other words: the malicious behavior would not require an explicit “run this script” step; it could trigger as a side-effect of normal application startup or import paths.

Chainguard also reports that the code “beaconed” to a specific domain:

  • igotnofriendsonlineorirl-imgonnakmslmao[.]skyhanni[.]cloud

Chainguard characterizes the likely purpose as credential harvesting or follow-on payload delivery. That “likely” matters: the post indicates intent and suspected outcomes based on observed behavior, but it does not claim confirmed exfiltration from any specific victim.

Chainguard says the malicious version has since been quarantined on PyPI, the compromised tag was removed from GitHub, and the container image was removed from Docker.

Who is affected vs. who is not#

Chainguard’s key claim is scoped and operational: customers using Chainguard Python Libraries and Chainguard Container images are “unaffected” by this incident.

The reason, per Chainguard, is their build pipeline behavior:

  • Chainguard’s “Factory” detected malicious patterns in 0.23.3 before building it.
  • As a result, Chainguard did not ship the compromised version in its artifacts.

Chainguard further states:

  • Chainguard Libraries includes 89 safe versions of elementary-data, including a “latest safe version” 0.23.4.
  • Chainguard Containers customers are safe because the package “was never added to any of our artifacts.”

The exposed population (again, per Chainguard’s description) is narrower but still large enough to take seriously:

  • Anyone who pulled elementary-data version 0.23.3 directly from the PyPI registry should treat it as potentially compromised.
  • Anyone who pulled the corresponding container from Docker Hub (as referenced by Chainguard) should also investigate.

Notably, Chainguard’s post does not quantify the number of downstream installs of 0.23.3, identify how the compromise occurred, or confirm what data (if any) was accessed. So the safest reading is: install or inclusion of 0.23.3 is the primary exposure indicator; impact severity depends on what ran and what secrets were present at runtime.

Why this matters (even if you didn’t use elementary-data)#

This incident fits a common supply-chain failure pattern: a popular dependency gets a malicious release, and the “blast radius” is determined less by the package’s advertised purpose and more by where it is imported.

Three practical implications:

  1. Import-time execution is a high-leverage tactic. If malicious code runs on import, you can be exposed in routine environments (CI, ephemeral job runners, dev laptops) where secrets are present and monitoring is weak.

  2. Containers do not automatically reduce supply-chain risk. If a container image is built from compromised inputs (base layers, pip installs, build steps), the image can become the delivery vehicle. The key is provenance and build controls, not the packaging format.

  3. “Pulled from registry” is an actionable pivot. Unlike vague advisories, Chainguard’s write-up gives a crisp indicator: version 0.23.3 from PyPI (and a related Docker Hub image) is the suspect artifact. That’s the starting point for triage.

What to do if you might have pulled 0.23.3#

If you maintain Python workloads, treat this like a dependency incident first, and a forensic incident second. Start with deterministic questions you can answer from logs and lockfiles.

Here are concrete checks and actions that follow from what is known:

  • Confirm whether elementary-data==0.23.3 was ever installed.

    • Search requirements.txt, poetry.lock, Pipfile.lock, uv.lock, requirements.lock, build logs, and CI caches.
    • If you use Docker, search Docker build logs for pip install elementary-data and inspect image layers/history.
  • If it was installed, assume the code may have executed.

    • Chainguard reports import-time execution, so “we didn’t run the tool” is not a reliable safety argument if the package was imported as part of application startup, tests, or plugin discovery.
  • Hunt for outbound connections to the reported domain.

    • Look for DNS queries, HTTP(S) traffic, or proxy logs that include skyhanni.cloud or the full hostname Chainguard listed.
    • Absence of logs is not proof of absence, but a hit is a strong escalation trigger.
  • Rotate and invalidate secrets that could have been present where the package ran.

    • Focus on CI tokens, cloud provider credentials, database passwords, and warehouse credentials (the natural environment for data tooling).
    • Prioritize environments where pip install occurred and where imports ran (CI runners, build agents, scheduled jobs).
  • Remove 0.23.3 and pin away from it.

    • Upgrade/downgrade to a version you trust (Chainguard points to 0.23.4 as a safe version).
    • Add explicit version constraints to prevent accidental reintroduction via floating ranges.
  • Preserve evidence if you need a confident answer later.

    • Snapshot the environment details (installed distributions, container digests, build artifacts) before you clean up.
    • If you have to involve IR later, “what exactly was installed and when” will matter more than recollections.

What not to overclaim: Chainguard’s post suggests credential harvesting or follow-on payload delivery as a likely motive, but it does not provide victim-level confirmation. Your response should be proportional: treat it as a serious potential credential exposure, but avoid stating breach facts you cannot support.

What to watch next#

The open questions are the ones that determine how you calibrate risk across an organization:

  • How the malicious release was introduced (maintainer account takeover, dependency confusion, CI compromise, etc.).
  • Whether the package had broad transitive inclusion (pulled in by other tools) versus direct installs.
  • Whether additional malicious releases existed beyond 0.23.3.

For teams building their own guardrails, the operational lesson is not “use this one vendor.” It is that build-time detection and strict artifact provenance can prevent compromised upstream releases from making it into production supply chains. Chainguard’s claim here is that their pipeline caught malicious patterns before the compromised version entered their shipped artifacts; that is the control worth mapping to your own environment.