The Rust supply-chain attack involving `arrayref`, `internment` and `append-only-vec` is particularly concerning because it demonstrates how attackers can compromise software before it ever reaches production. The malicious code did not need to exploit the finished application. It executed during compilation, meaning developer workstations and CI/CD build servers became the actual targets. The Rust Project confirmed that malicious releases were uploaded to crates.io on August 20, 2026 after a maintainer account was compromised, and that the malicious versions were removed within roughly 86 to 107 minutes. Despite that relatively short exposure window, the affected crates sit deep inside dependency trees used by a very large number of Rust projects. `arrayref` alone has accumulated roughly 245 million downloads over its lifetime.
The most important compromised release was `arrayref` 0.3.10. The legitimate `arrayref` crate had existed for years without dependencies, but version 0.3.10 suddenly introduced a dependency on a package named `proc-macro1`. The name was carefully chosen to resemble the extremely popular legitimate Rust crate `proc-macro2`. The attacker even created a crates.io account named `dtolney`, visually similar to legitimate Rust developer David Tolnay's `dtolnay` identity, and used forged author metadata to make the package appear more believable. This combination of account compromise and typosquatting is important because developers were not simply tricked into downloading an obviously unknown package. A trusted package was modified to pull the malicious dependency automatically.
The malicious behaviour was placed inside the `build.rs` file of `proc-macro1` 1.0.107. Rust's Cargo build system automatically executes build scripts while compiling dependencies. Consequently, a developer did not need to call a malicious function or even use functionality from `proc-macro1`. Merely running a build that resolved the compromised dependency was sufficient to execute the attack. This is what makes build-time supply-chain attacks particularly dangerous. The malicious code runs before the resulting application exists and with whatever privileges and secrets are available to the developer or CI process performing the build.
The attacker's `build.rs` reconstructed its infrastructure from encoded fragments, connected to `23.254.165.112` on port 9089, downloaded a second-stage payload appropriate for the victim's operating system and architecture, and executed it. On Unix systems the payload was written to `/tmp/rust-setup`; on Windows, the attack used files such as `%TEMP%\rust-setup.ps1` and `%TEMP%\rust-setup-launch.vbs` and launched the process in a manner intended to keep execution hidden from the normal build workflow. The script also disabled proper TLS certificate verification, accepting any certificate presented by the payload server. A separate address at `23.254.165.112:443` was supplied to the downloaded payload as its command-and-control destination.
The attack was made more deceptive because the actual Rust library code inside `proc-macro1` closely resembled legitimate `proc-macro2` code. As a result, the dependency could compile successfully while the malicious activity occurred in the build script. From a developer's perspective, nothing necessarily had to fail. The project could build normally while a second-stage binary was quietly launched in the background. This is precisely the kind of supply-chain compromise that traditional source-code review can miss when reviewers focus primarily on the application's own source rather than manifests, dependency changes and build-time behaviour.
The attacker also appears to have manipulated Cargo's normal package-management behaviour to push developers toward the compromised version. Older `arrayref` versions 0.3.5 through 0.3.9 were yanked shortly after 0.3.10 was published. Cargo can warn developers when they are using a yanked package and suggest updating to a non-yanked release. In this case, blindly following the apparently sensible advice to update could have moved a developer directly onto the malicious release. This is an important supply-chain lesson: a newer package version is not automatically a safer package version, and automated dependency updates need security controls around them rather than unconditional trust.
The other malicious releases, `internment` 0.8.7 and `append-only-vec` 0.1.9, were published from the same compromised owner account and used the same underlying technique. The Rust Security Response Team subsequently deleted several attacker-created crates, including `proc-macro1`, `proc-macro-en`, `aovine`, `arone`, `aronenao` and `tinymember`. The rapid response substantially reduced the exposure period, but deleting a malicious package from the registry cannot reverse execution that has already occurred on a developer's machine or CI runner.
The potential blast radius is significant because dependencies such as `arrayref` may appear several layers below the application developers actually selected. Researchers traced it through dependency chains involving `tiny-skia`, `sctk-adwaita` and `winit`, placing it below frameworks such as egui, eframe and iced. It also appears in dependency ecosystems associated with cryptographic libraries and blockchain projects. A development team may therefore never have deliberately selected `arrayref`, yet Cargo could still resolve and build it because another dependency required it. This is why software supply-chain inventories need to include transitive dependencies rather than only the packages explicitly declared by developers.
It is equally important not to misinterpret the 245-million-download figure. That number represents the historical popularity of `arrayref`, not 245 million compromised machines. The malicious release existed for only a short period, and the Rust Project stated that it had found no evidence that the malicious versions were actually used. However, absence of evidence at the registry level cannot guarantee that no machine executed the malicious build script. Any organisation that resolved one of the affected package versions during the exposure period should perform its own investigation rather than relying entirely on aggregate download statistics.
Organisations using Rust should first inspect `Cargo.lock` files and local Cargo caches. The presence of `arrayref` 0.3.10, `internment` 0.8.7, `append-only-vec` 0.1.9 or the malicious `proc-macro1` dependency should trigger investigation. Administrators can also examine `~/.cargo/registry/cache` because deleted crates can remain cached locally even after crates.io removes them. This is an important detail: takedown from the public repository does not magically delete copies already downloaded into developer laptops or CI caches, apparently because package managers have not yet acquired supernatural remote-cleanup abilities.
Affected systems should also be checked for the known execution artefacts, including `/tmp/rust-setup` on Unix systems and `%TEMP%\rust-setup.ps1` or `%TEMP%\rust-setup-launch.vbs` on Windows. Network telemetry should be searched for communication with `23.254.165.112` on ports 9089 and 443. If any of these indicators are discovered, the machine should be treated as compromised rather than simply deleting the suspicious file. The malicious build script downloaded and executed a second-stage payload, and the complete functionality of that payload was still being investigated at the time of disclosure.
This distinction is particularly important for CI/CD systems because build servers often contain extraordinarily valuable secrets. They may hold GitHub or GitLab tokens, cloud API keys, package-registry credentials, SSH keys, deployment certificates, code-signing keys and credentials capable of deploying directly into production. If malicious build code executes within such an environment, stealing the application's source code may actually be one of the less valuable outcomes. A compromised signing key or deployment token could allow an attacker to continue the supply-chain attack further downstream and produce software that appears legitimately signed by the victim organisation.
Any CI runner or developer workstation confirmed to have executed the malicious package should therefore be isolated and investigated, and credentials accessible to that environment should be rotated. This includes cloud credentials, source-control tokens, package-publishing tokens, deployment secrets and signing keys. Builds produced after the suspected compromise should also be considered untrusted and rebuilt in a known-clean environment from verified source and dependencies. Simply rerunning the build after deleting `proc-macro1` does not provide assurance that credentials or build artefacts were not already modified.
One of the strongest preventive measures is deterministic dependency management. Production and release builds should normally use committed lockfiles and commands such as `cargo build --locked` so that dependencies cannot silently change simply because a new package release appears in crates.io. Dependency updates should be deliberate changes reviewed through the same code-review process as application changes. An unexpected new dependency in a long-established package, particularly one adding a `build.rs`, native code or network-capable functionality, deserves scrutiny before entering trusted build infrastructure.
Organisations should also introduce a cooling-off period for newly published dependencies where operationally possible. The malicious `arrayref` release survived for approximately 86 minutes. A policy preventing CI from automatically consuming packages published within the previous 24 hours, several days or another defined period would have prevented this specific attack from reaching production build environments. Rust's Cargo ecosystem has been discussing a `min-publish-age` capability for precisely this reason, and the incident has understandably accelerated interest in such controls.
Build environments themselves should also be sandboxed. A Rust `build.rs` script currently executes code during compilation, so from a security perspective dependencies should be treated as executable content rather than passive source libraries. CI jobs should run inside isolated, disposable environments with minimal privileges, no unnecessary access to developer home directories and carefully restricted network connectivity. Where possible, build containers should be destroyed after each job rather than reused indefinitely.
Outbound network restrictions can be exceptionally effective against this category of attack. Most software compilation processes do not need arbitrary Internet access once required source packages have been downloaded through an approved repository proxy. A malicious build script trying to connect directly to an unfamiliar IP address on port 9089 should therefore be blocked at the network layer. Allowing build servers unrestricted Internet access effectively gives every transitive dependency permission to download anything it wants during compilation, which is an impressively generous security model for code written by strangers.
Enterprises should consider routing package downloads through an internal registry or repository proxy rather than allowing every developer workstation and CI runner to communicate directly with public package repositories. This creates a control point where dependencies can be scanned, approved, cached and subjected to organisation-wide policies. Packages containing unexpected build scripts, newly created publisher accounts, unusual dependency additions or known malicious indicators can then be blocked centrally rather than relying on every developer to notice something suspicious.
Dependency provenance is another important defence. Organisations should increasingly ask whether a published package can be cryptographically tied to a trusted source repository and build process. In this attack, the malicious package publication could diverge from what developers might expect to see in the legitimate source repository. Strong provenance, signed releases and reproducible builds make it harder for an attacker who compromises only a package-registry account to publish arbitrary code without creating detectable differences between the repository and the distributed package.
Maintainer-account security is equally critical. A single compromised publishing account was sufficient to poison multiple legitimate crates. Package maintainers should use phishing-resistant MFA wherever supported, hardware security keys for critical accounts, narrowly scoped publishing tokens and short-lived credentials. Organisations maintaining popular open-source components should treat registry publishing credentials with security comparable to production deployment keys because, from a supply-chain perspective, they effectively are production deployment keys for every downstream consumer.
Security monitoring should also extend into the development pipeline. Endpoint detection systems should flag compiler or package-manager processes that unexpectedly spawn PowerShell, VBScript, shells, download utilities or unknown binaries. Network monitoring should baseline normal CI destinations and detect direct connections to raw Internet IP addresses. Build logs should be centrally retained, while unexpected modifications to lockfiles, package manifests and dependency graphs should generate review events.
The attack also demonstrates why software composition analysis must move beyond searching for CVEs. `proc-macro1` was malicious by design rather than vulnerable, and there was no CVE to detect. A scanner focused exclusively on known vulnerability databases could therefore report a completely clean dependency tree while the build system was actively downloading malware. Supply-chain security needs additional signals such as package reputation, publisher identity, package age, dependency changes, suspicious build scripts, typosquatting detection and unexpected network behaviour.
There is a broader architectural lesson here. Developers traditionally think of dependencies as code that becomes part of the application. Modern build systems make that assumption incomplete. Dependencies can execute code while compiling, generate source files, invoke external tools, contact networks and interact with the build machine. The effective trust boundary therefore begins when the package is downloaded and built, not when the finished program is executed.
This also changes how organisations should think about their CI/CD infrastructure. Build systems should be treated almost like production systems because they possess the authority to manufacture production software. In some respects they deserve even tighter controls. Compromise production and an attacker may control one deployed environment; compromise the build pipeline and the attacker may be able to distribute compromised software to every environment and potentially every customer.
The Rust response was commendably fast. The malicious crates were identified, removed and related packages deleted within a relatively short period. But the real lesson is that ecosystem response speed cannot be the only security control. Even an 86-minute malicious-package window is enough for automated CI systems operating around the world to download and execute a dependency. Modern build pipelines move considerably faster than human security teams, which is wonderful for software delivery and rather convenient for supply-chain attackers.
Organisations should therefore respond by combining dependency pinning, lockfile enforcement, delayed adoption of newly published packages, repository proxies, provenance verification, build isolation, least-privilege CI credentials, restricted outbound connectivity and behavioural monitoring of build processes. Any environment known to have built the malicious releases should be investigated as a potentially compromised endpoint, with accessible credentials rotated and subsequent artefacts rebuilt from clean systems.
The most important takeaway from this incident is that supply-chain attackers do not necessarily need to compromise the software delivered to customers. If they can compromise the process that creates that software, they are already standing inside one of the most trusted parts of the organisation. The `arrayref` incident demonstrates how one compromised maintainer account, one convincing typosquatted dependency and one malicious `build.rs` can convert an ordinary `cargo build` into remote code execution. In modern software development, protecting the build environment is therefore no longer merely a DevOps concern. It is a fundamental part of enterprise security.

The Rust Project has deleted malicious versions of three widely used Rust crates from crates.io after a compromised maintainer account published releases that added a typosquatted dependency whose build script downloaded and executed a remote payload during compilation. The affected releases are arrayref 0.3.10, internment 0.8.7, and append-only-vec 0.1.9, all published from the same owner
Source: Rust Supply Chain Attack Puts Build-Time Malware in Crates with 245 Million Downloads via The Hacker News — published 20 Aug 2026.
Was this article helpful?
Your feedback helps us improve the knowledge base.