
๐ค Ghostwritten by GPT 5.4 ยท Fact-checked & edited by Claude Opus 4.6
On 2026-06-01, researchers disclosed the Miasma attack, a supply-chain compromise affecting Red Hat npm packages. The most important lesson is simple: npm install is not a passive download step. It can run other people's code on your machine before your application ever starts. That same risk exists in other ecosystems too, including Python package installs in many configurations.
According to reports from Wiz and Microsoft Security, at least 32 packages under Red Hat's official npm namespace were poisoned across 96 versions after an attacker compromised an employee account and abused trusted publishing. Wiz reported the affected packages accounted for roughly 117,000 weekly downloads at the time of disclosure. That matters because this was not typosquatting, not a fake lookalike package, and not a dependency confusion trick. It was a compromise of a legitimate publisher path.
For developers โ especially fast-moving builders and vibe-coders โ the durable takeaway is bigger than this one incident: installing a dependency is executing code from outside your project. Package installation deserves the same caution as running a shell script from the internet.
TL;DR: Miasma worked because attackers got into a legitimate publishing path, so "it's from a big company" was not enough protection.
The Miasma attack stood out because it abused trust that many teams assume is safe by default. Researchers reported that an attacker compromised an employee's GitHub account and then used GitHub Actions OIDC-based trusted publishing to release malicious versions under Red Hat's official npm namespace. The attacker did not need to create a fake package name โ they published as if they were the real maintainer.
Wiz disclosed the incident on 2026-06-01, and Microsoft Security published additional analysis on 2026-06-02. Both described a malicious install-time script that executed immediately when the package was installed. Microsoft characterized the campaign as credential-stealing and noted behavior aimed at persistence and spread in automated environments. Wiz reported the package used a 4.29 MB obfuscated dropper and, in CI/CD environments, attempted worm-like propagation by abusing build context and forged provenance records.
That distinction matters because many dependency hygiene habits focus on spotting obvious fakes:
Those checks still matter, but Miasma shows they are incomplete. A trusted namespace can still become a delivery channel for malware if the publisher account or publishing workflow is compromised.
Trusted publishing is generally a good security improvement. Instead of storing a long-lived token in a CI system, the build platform proves its identity and gets short-lived permission to publish. That reduces one class of secret leakage.
But trusted publishing does not solve account compromise. If an attacker gains control of the source account or workflow that the registry trusts, they can still publish malicious artifacts through the legitimate path. The system can be cryptographically valid and still operationally compromised.
| Threat type | What it looks like | Was this Miasma? | Main defense |
|---|---|---|---|
| Typosquatting | Fake package with a similar name | No | Verify names and publishers |
| Dependency confusion | Wrong package source gets selected | No | Configure registries and scopes correctly |
| Official publisher compromise | Real namespace publishes malicious code | Yes | Reduce install-time execution risk; review updates carefully |
For anyone shipping software in 2026, that leads to a more realistic rule: trust signals help, but they do not remove the need to control what runs during installation.
TL;DR: Install scripts are automatic commands a package manager runs during installation, which makes them a perfect place to hide malicious behavior.
An install script is code a package author tells the package manager to run while the package is being installed. In npm, common lifecycle hooks include preinstall, install, and postinstall. These scripts can do legitimate work:
The problem is not that install scripts exist. The problem is that they run automatically, often before a developer has looked closely at what changed.
If a package contains a preinstall script, npm executes it as part of the install process โ before your application code runs, and often before you have any practical visibility into what it is doing unless you inspect the package contents or logs carefully.
Attackers favor this location for several reasons:
A malicious preinstall script runs at the moment of installation. The victim may think they are only fetching dependencies, but code execution has already started.
Developers install packages on laptops, build agents, and CI runners. Those environments often contain valuable credentials: SSH keys, cloud CLI tokens, browser session data, or wallet artifacts.
Most teams install and update dependencies constantly. Install-time execution feels routine, which lowers suspicion.
In build systems, an install script may run with access to repository tokens, environment variables, caches, and publishing credentials. That can turn one compromised dependency into a broader supply-chain event.
A useful mental model: installing a package is closer to running an installer than downloading a zip file. Once that clicks, the security implications become much easier to understand.
TL;DR: The fastest risk reduction is to disable install scripts where possible, pin versions, review lockfile diffs, and avoid installing packages on high-trust machines.
Miasma is a strong reminder that dependency installation needs guardrails. A few habits can materially reduce exposure.
In npm, the common option is --ignore-scripts. That prevents lifecycle hooks like preinstall and postinstall from running automatically.
npm install --ignore-scriptsThis is a risk-reduction step, not a universal switch. Some packages legitimately need install scripts โ especially packages that compile native code or fetch platform-specific components. The practical pattern is:
For Python and other ecosystems, the exact controls differ, but the principle is the same: understand whether install-time code executes, and minimize it where possible.
When adding or updating a dependency, inspect the lockfile diff. Lockfiles record the exact versions and dependency tree your project resolved.
Look for:
A lockfile is not glamorous, but it is often the clearest record of what actually changed.
Avoid loose version ranges when possible. Pinning versions makes installs more predictable and reduces surprise updates.
| Practice | Why it helps | Tradeoff |
|---|---|---|
| Pin exact versions | Reduces surprise changes during install | Requires more deliberate updating |
| Use lockfiles in CI | Keeps builds reproducible | Lockfiles need review discipline |
| Disable scripts by default where feasible | Cuts off a major execution path | Some packages may fail until handled explicitly |
| Separate dev and high-trust environments | Limits blast radius if install-time malware runs | Adds workflow friction |
Do not treat a laptop full of SSH keys, production cloud access, browser sessions, and crypto wallet extensions as the safest place to experiment with new dependencies. If possible, isolate dependency evaluation in:
Many developers now rely on AI tooling to explain unfamiliar dependency trees. That can help here too, especially with a specific request.
Paste-able prompt:
Review this project's dependency tree and identify which direct and transitive dependencies run install-time scripts such as
preinstall,install, orpostinstall. For each one, explain why the script exists, whether it appears necessary, and what would likely break if scripts were disabled. Then recommend the safest installation approach for this project, including whether--ignore-scriptscan be used initially, which packages may need manual rebuild or approval, what lockfile changes should be reviewed, and any dependencies that deserve extra scrutiny because they download binaries or execute shell commands during install.
That prompt will not replace human judgment, but it turns a vague concern into a concrete review checklist.
TL;DR: The right default assumption is that dependency installation is code execution, not just file retrieval.
The biggest value of the Miasma attack as a teachable moment is conceptual. Many developers still think of installation as setup and execution as something that begins when the app launches. In modern package ecosystems, that distinction is often false.
By the time a developer runs the app, several things may already have happened:
Dependency security is not just about what libraries do at runtime. It is also about what they do during acquisition.
The Wiz disclosure on 2026-06-01 and Microsoft's follow-up on 2026-06-02 make this lesson unusually clear because the attack path was so direct: a legitimate namespace, a malicious preinstall path, credential theft, and attempted spread in CI/CD contexts. The details are modern, but the durable lesson is timeless: the moment of install is part of your attack surface.
The long-term implication of Miasma is not that package ecosystems are unusable. It is that teams need a more accurate default assumption: dependency installation is an execution event with supply-chain risk attached. The developers who adapt fastest will not be the ones who trust less in general, but the ones who trust more precisely.
An install script is a command a package can run automatically during installation. In npm, lifecycle hooks such as preinstall, install, and postinstall may execute before the package is ever used in your application. These hooks are defined in the package's package.json and run with the same permissions as the user invoking npm install.
It demonstrated that even packages from a legitimate, official publisher can become malicious if the publishing account or workflow is compromised. Unlike typosquatting or dependency confusion, the package names and namespace were genuine โ the trust signal itself was weaponized.
It reduces risk by blocking a major automatic execution path, but it is not a complete security solution. Some packages legitimately need install scripts to compile native addons or fetch platform binaries. There are also other supply-chain risks beyond lifecycle hooks, such as malicious runtime code that only activates when your application imports the package.
Review exact versions, newly introduced transitive dependencies, unexpected source changes, and any broad dependency churn that seems larger than expected. A small feature addition should not silently reshape a large part of the dependency tree. Tools like npm diff or lockfile-lint can help automate parts of this review.
No. npm is a prominent example because lifecycle scripts are common and well-documented, but install-time code execution exists in other ecosystems too. Python's setup.py can run arbitrary code during pip install, and similar mechanisms exist in Ruby gems and other package managers. The broader lesson is to understand what your package manager may execute during installation.
preinstall are useful for legitimate setup tasks and equally useful to attackers hiding malicious behavior.--ignore-scripts or equivalent controls where feasible, but treat it as risk reduction rather than a perfect fix.Discover more content: