Top
Best
New

Posted by abhisek 8 hours ago

Malicious Rust crate Arrayref runs a build-time payload(safedep.io)
https://blog.rust-lang.org/2026/08/20/supply-chain-attack-on...

https://github.com/rustsec/advisory-db/issues/3161

317 points | 290 commentspage 2
hoppp 5 hours ago|
The rust ecosystem is going to be hit by malware just like the NPM ecosystem. I have been saying it for years. They made the same mistakes or even worse mistakes because all it takes is a compromised serde to take the entire ecosystem down.
leecommamichael 4 hours ago|
Here's a suggestion, do you think it could be this simple? If you write a package-manager, don't execute any of the downloaded code in an automated fashion. No hooks, no build-time metaprograms. If your language _needs_ metaprogramming to function, it's a huge secondary issue that I don't know how to solve. You can try to make a meta-program annotation which disables side-effects, but the metaprogram ultimately must write memory which expands the amount of code generated. All risk is introduced when the person downloading cannot preview the content in a safe place.
zarzavat 2 hours ago|||
Unfortunately it doesn't solve the problem because malicious code can still end up compiled into the user's program which they will promptly execute, possibly in production...

Supply chain attacks are not a problem that can be solved by a single silver bullet, however the biggest benefit comes from a combination of minimum release age + fresh 2FA required for every publish + automated scanning. This makes it considerably more difficult to pull off a supply chain attack and should be the baseline security for all package managers.

jaen 48 minutes ago|||
The only safe solution is to review all the code's changes (or trust someone else to do it).

Forbidding compile/build-time shenaningans is trivially bypassable and has already been bypassed in the NPM ecosystem by just making the library code itself (not the build scripts) malicious - eg. do the bad thing when the code is loaded/tested, assuming the language has static constructors.

killme2008 3 hours ago||
We really need Cargo RFC #3923 https://github.com/rust-lang/rfcs/pull/3923

It would allow projects to avoid newly published dependency versions until a configurable waiting period has elapsed.

npm has had a similar min-release-age feature for years.

killme2008 3 hours ago|
It's a pity that progress has been so slow.

https://github.com/rust-lang/cargo/issues/17009

tsimionescu 7 hours ago||
> arrayref is a small crate of four macros.

Why do so many languages fall into this horrible practice?

wasmperson 7 hours ago||
There was a recent talk which explored this question (Dependency Cultures, by Richard Feldman):

https://www.youtube.com/watch?v=E82ly38YEEQ

Summary: it's cultural. Rust likely inherited the practice from Nodejs, who inherited it from Ruby. I think in Rust online spaces in particular there is also this undercurrent of "you're not smart enough to use certain parts of the language, so download libraries that handle that stuff for you."

igsomething 6 hours ago|||
The language also takes backwards compatibility very seriously, anything that goes into std "must be maintained forever". It is also argued that a large stdlib means the maintainers have less time to work on the language itself.

I understand not every language can have Go's amazing stdlib, but I would much prefer Pyhton's approach where every now and then some package/function from the stdlib gets deprecated/removed. Rust's 3rd party ecosystem is the worst thing from the language, worse than the compile times.

superxpro12 6 hours ago||||
i'd like to welcome you to the hell that is c/c++ dependency management. Make? cmake? qmake? conf? autoconf? configure? autotools? submodules??? AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
nelup20 6 hours ago|||
Conan, Meson, Ninja, Bazel, meta-build tool / dependency manager #231 etc. etc. And then you have to deal with all the modern C++ and STL footguns.

It never ends .·°՞(っ-ᯅ-ς)՞°·.

bayindirh 6 hours ago||||
I'd just select a tool, vendor the libraries I need to the codebase and call it a day. Did these for Eigen, liboption++, Catch2, Easylogging++ (now archived and not maintained anymore, sadly).

Build a simple makefile, and you're off to the races.

At least, for my cases, that is.

account42 5 hours ago||||
I'll take all that over downloading and immediately executing random unreviewed code any day.
skydhash 6 hours ago||||
None of those (other than submodules which is just vendoring) does dependency management. They are more configuration management than anything. C, Python, Perl (and maybe ruby?) relies on flag switches and environment variables to find all the necessary files and modules for compiling/running a script. Cmake and autoconf just configure those.

With NPM and Rust's focus on project's level dependencies, there's no longer emphasis on API stability. Instead we have breakage every months, forcing everyone on the upgrade treadmill. It's easier to audit C library because they focus mostly on security updates instead of redesigning the API for the nth time.

SSLy 6 hours ago||||
xmake, build2, whatever msvc and xcode insist upon…
justinhj 6 hours ago|||
vcpkg is pretty good. cmake is complex but very flexible. just need an llm to help and it's pretty much solved (if your dep is in autopkg)
neutronicus 6 hours ago||||
The "npm-ness" of Cargo (centralized and standardized dependency management used at every opportunity) is generally pitched as one of the primary developer experience advantages over C++.
pjmlp 2 hours ago||
For those missing the npm like experience in C, they can use apt, yum, dnf, winget, nuget, conan, vcpkg.
irishcoffee 7 hours ago|||
[flagged]
ux266478 6 hours ago|||
Rust as a language is mostly alright in my opinion. The problems I have with it are similar to the problems I have with C++, and it makes up for them in other really compelling ways.

Where it loses me is Cargo and everything surrounding it. I'm essentially forced into an extreme where I just never use anything in the Rust ecosystem, or I have to deal with insane dependency graphs that have the density and microstate complexity of a neutron star.

andsoitis 6 hours ago||
> Rust as a language is mostly alright in my opinion.

> Where it loses me is Cargo and everything surrounding it.

High praise!

josephg 6 hours ago|||
> Rust is very much a schlong-measuring contest

What? Its just a programming language. Go dependency free if you want. Or vendor everything. Nobody is forcing you to pull in 3rd party dependencies.

silverlinex 6 hours ago||
[flagged]
bayindirh 6 hours ago||
As a person who doesn't like Rust very much, no, it doesn't suck. Some of its features make some folks very excited for very right reasons, and evokes "Silver Bullet Syndrome" in others for all the wrong reasons.

People weaponizing Rust rewrites with permissive licenses is another problem, but it's not about the programming language itself.

vablings 6 hours ago|||
There are two reasons you might want to use a crate, The first being that you want to use a good solid implementation that you know someone has spent more time doing and works better than almost any solution you could integrate. The second is you don't want to spend time implementing that.

Writing macros in rust is a pretty horrible experience but it's not difficult

xdavidliu 1 hour ago|||
just to clarify, by "horrible practice" you mean macros?
Narishma 47 minutes ago||
No, they probably mean tiny libraries.
tsimionescu 19 minutes ago||
Yes, that's what I meant.
bcjdjsndon 7 hours ago|||
Just like c++ thought threads wasn't a std library concern and then later changed they minds, rust will also change tac I predict
nicoburns 7 hours ago||
Rust is actively incorporating more functionality into the stdlib. The functionality of this crate has been in std since 2024. The ecosystem is just slow to update (not everything is maintained, etc).
silverlinex 6 hours ago||
[flagged]
chaps 6 hours ago||
Are you okay?
rvz 7 hours ago|||
The languages that have a poor standard library support have this issue and other languages encourage you to import tons of libraries to fix the problem.

This is why Javascript and Typescript suffer from this the most and has little to nothing to do with "popularity" and likely 9/10 of these npm packages import an external library.

Golang on the other-hand is just as popular and has a stronger standard library which people build against and it is encouraged to use its standard library rather than rolling your own or importing another package to solve the problem.

weinzierl 7 hours ago|||
Rich official standard library vs "import tons of libraries" are not the only two options.

Java's standard library had arguably also been poor for a very long time and "import tons of libraries" just had not been practical for most of that time because the tooling and ecosystem for that did not exist yet.

The solution was apache-commons and guava. Two large libraries with everything the developers heart desired and well maintained by large organizations.

For Rust be probably will never have anything exactly like that because requirements from no-std development to fully fledged backend service are too diverse, but there is still room for a small number of well maintained backed by reputable developers convenience libraries in my opinion.

wahern 4 hours ago||
Namespacing. Mandatory namespacing. It's an essential prerequisite for any kind of reputation building and managememt, before you even get into the gritty technical or security details.

And it has to be mandatory. Top-level package names will always have more cachet. Developers are suckers for good package names, literal or imaginative. Plus it helps address, but by no means completely solves, name and typo squatting.

I understand people and groups can run their own crates.io-like repository, but that's a tangential aspect. Even if this were ubiquitous, you'd still want mandatory namespacing. You want provenance, or at least intended/nominal provenance, to be as transparent as possible, not implicit or buried. By no means a complete solution, but an important foundation for better technical and culture patterns.

trembolram 6 hours ago||||
I don't want to see a large standard library for Rust. If something is added to the standard library, then it is very difficult to change it afterwards because backwards compatibility.

It would be better to have blessed crates in crates.io. The Rust core team would release or audit them. If the blessed crates need breaking changes, it can be done by increasing their major semantic version number. That can't be done to the standard library.

Actually, there could be a "trust" level for crates: 1. blessed crates by the Rust core team, 2. trusted developers, 3. untrusted developers. Or something like that..

sfdsfef3f3f 6 hours ago||||
Go has a stronger standard library for certain use cases like basic CRUD web applications, but a lot of the Go standard library is also extremely low quality (flag, container, image, json, log, math, path, regexp, sync, time). Many of these aren't usable outside of toy use cases and have weird edge cases all over the place. Over time many will probably get new incompatible versions just like json. The container package in Go is the worst collection library in any mainstream programming language by a huge margin. It's actually astounding how bad it is.
Mawr 3 hours ago||
FYI, json/v2 just dropped: https://go.dev/doc/go1.27#jsonv2 and log/slog has been a thing since 1.21: https://go.dev/doc/go1.21#slog

> a lot of the Go standard library is also extremely low quality

Now adjust your definition of "a lot" to include all other languages instead of apparently arbitrarily deciding that "a lot" means at best 10 and pretending that "weird edge cases all over the place" isn't normal.

I also wonder what your issue is with most of those, especially since e.g. regexp is excellent in the context of this thread - it runs in linear time, so it's not possible to craft a malicious input that will make it slow down to a crawl.

> Over time many will probably get new incompatible versions just like json.

What a bizarre statement to make.

FYI: "The encoding/json package is now backed by the v2 implementation.". You get all the benefits possible from the v2 implementation for free while maintating backwards compat and if you want to upgrade to something better, v2 is right there.

Do you have some magical suggestion how this could have possibly been handled better? And no, not having json in the stdlib isn't a viable path, that's just a cop out. But I guess since e.g. Rust and Java don't have json in their stdlibs at all, you can't say their json packages are bad, how clever and smart!

Another frequently made suggestion straight from la-la land is just writing perfect code from the get-go. Brilliant, can't believe nobody's ever thought of that.

Meanwhile in the real world, you've been able to reap the benefits of the solid encoding/json for over a decade now, and with v2 you get some nice free backwards compatible improvements and have a clear path to upgrading to v2. Perfectly handled IMO.

sfdsfef3f3f 3 hours ago||
> Another frequently made suggestion straight from la-la land is just writing perfect code from the get-go.

The code in those packages is so far from perfect it's absurd. Like most Go developers, you just have extremely low standards.

wasmperson 7 hours ago||||
I don't think this is true. People like to scapegoat the JS standard library but in reality most JS implementations have pretty featureful standard libraries, especially browsers. I've never felt the need to use any third-party libraries in the javascript projects I've worked on (except for maybe `ws`).
tsimionescu 7 hours ago||||
I don't think it's just that, though I agree they are clearly correlated.

The reason I don't think it's a sufficient explanation is that there is a clear history of large, 3rd party libraries being created exactly to supplement poor standard libraries. C++ has Boost, Java has Apache Commons (though Java also has a pretty huge standard library), arguably we could even say C has Posix/Win32/Cocoa.

I believe there is some deeper cultural reason why certain language ecosystems coalesce large utility libraries, while others prefer myriad tiny dependencies.

whstl 6 hours ago|||
The important difference IMO is in the small vs big libraries culture.

Lots of languages have a bad stdlib but don’t fall into the trap of having thousands of micro libraries.

The reason people do it is because it brings clout and money. Just look for articles defending micro libs: the popular ones are by people who make a living on donations, due to maintaining 1000+ packages.

And collaborating in larger libs/stdlib is hard. Plus: Rust, Node, all have a lot of visibility.

You need a good stdlib culture to avoid it (like Go did).

DanielHB 6 hours ago|||
The reason is simple: the package manager works well. Helps if the package manager is standardized and there is a "default" registry for open source projects.

I remember the days where I had to manually put the Spring .jar files into my project. No way I am doing that for 100s of dependencies.

bryanlarsen 7 hours ago||||
I've never seen a non trivial Python or Go project without external dependencies. The dependency tree of comparable Go and Rust projects seem comparable, IMO.
QuadmasterXLII 5 hours ago||
Pytorch has 9 transitive dependencies for cpu-only execution, or 29 to bring in cuda.

candle, the most popular rust ml library I found in a cursory search, has 119 for cpu only, and 150 to bring in CUDA.

I guess it's taste whether that's comparable

this would have been a way more satisfying dunk if nvidia hadn't split the cuda functionality needed by pytorch into 19 (!) packages on pypi but such is life.

bryanlarsen 3 hours ago||
I expected somebody to pull out an example "disproving" my point. It wouldn't be hard. I can point out rust projects that have a ton of external dependencies, and then point at similar projects with very few.

But a Python example doesn't really count, in my mind -- Python is pre-GitHub so tends to have small numbers of large external dependencies, like C++ and other older languages.

QuadmasterXLII 3 hours ago||
If a python example doesn't count, why were your two example languages python and go?

But yeah, small number of large dependencies is the way to go.

insanitybit 6 hours ago||||
Total nonsense. Python has a massive stdlib and there are malicious packages.
fukaiall 6 hours ago|||
Can’t agree more. If you take security seriously, you should consider using Go.
account42 5 hours ago|||
Only the ones that make it easy. Language package managers are a mistake.
pjmlp 2 hours ago||
Unfortunely we haven't yet gotten a universal OS agnostic package, other than zip and tarballs.
MallocVoidstar 7 hours ago||
They aren't trivial, at least: https://docs.rs/arrayref/0.3.9/src/arrayref/lib.rs.html#202-...
praseodym 7 hours ago||
Post on the Rust blog: https://blog.rust-lang.org/2026/08/20/supply-chain-attack-on...

Discussion: https://news.ycombinator.com/item?id=49372853

praseodym 8 hours ago||
Unfortunately Cargo doesn’t have security controls in place to prevent these kinds of attacks. For example pnpm has controls to allowlist install scripts for dependencies and will warn about new install scripts (without executing them).

There is an open issue for this: https://github.com/rust-lang/cargo/issues/13681

weinzierl 7 hours ago|
Compromising the code that is then most likely run in a test instead of compromising a build script is just a very slight inconvenience for the attacker.

I share the dislike for arbitrary build scripts but restricting them will not help the supply chain issue in a significant way.

Also there are several ways to control build.rs execution in the Cargo ecosystem as well, for example with cargo-deny.

praseodym 7 hours ago|||
You’re right about attackers being able to change runtime code.

pnpm does have some other features to prevent supply chain attacks, so there is still something to learn from other ecosystems. For example pnpm has a cooldown period for new dependencies and can prevent trust policy downgrades (eg new version published without build provenance where older versions did have it). See https://pnpm.io/supply-chain-security

faern 6 hours ago||
> pnpm has a cooldown period for new dependencies

Cargo has `min-publish-age` in nightly, and it's currently heading towards stabilization: https://github.com/rust-lang/cargo/pull/17335

vlovich123 7 hours ago||||
Disallow lists are ineffective - better to disallow by default and require opt in.

Also, crates.io can defer serving up newly uploaded scripts that have a new build.rs / proc-macro dependency and warn publicly that a version introduces it.

Restricting build scripts 100% will help mitigate the impact, just not if you only deny it once. And they can develop other things like sandboxing for build scripts by default and escaping that to be the exception that has to be explicitly allowed.

Aeolos 6 hours ago|||
The problem is that build scripts run automatically without user consent or intevention.

`cargo add` is sufficient to compromise you, before you have a chance to even vet the code.

kibwen 2 hours ago||
`cargo add` just modifies your Cargo.toml, it doesn't build anything.
abbadadda 6 hours ago||
Are there any plans to more seriously develop the standard library in Rust? Or is the plan to remain in this status quo where users of Rust import nonsense and the dependency tree explodes (or users are forced to invent their own wheel?).

Are there any comparisons between the state of the stdlib in C++ vs. Rust? I’d think that would serve as an excellent jumping off point to start chipping away.

speedstyle 3 hours ago||
The standard library is not versioned, so any API*/behaviour there must be maintained forever. When you put it in a separate crate, you can make better interfaces or be displaced by a better crate, while old code still compiles against the version it was written for. So even code effectively maintained within rust teams (hashbrown, rand, regex) may be in separate crates, std is specifically for OS abstraction and a shared type vocabulary.

That doesn't mean you jump to importing nonsense or trivial dependencies. The top hundred are efficient, well-designed crates of the quality you'd expect in a large std like Go or Swift, sometimes even higher as people can write better implementations that they otherwise wouldn't (or wouldn't be used over std). And those languages make breaking changes! C++ is mostly stable, so it's full of junk like <regex> or just unordered_map. Rust managed to wholesale reimplement HashMap 6 months after SwissTable released, like it is also easier to express this level of encapsulation, but that's part of countless design/interface decisions made deliberately to not constrain forwards compatibility, including a smaller std.

However, that's no excuse to have a worse developer experience in this area. We need better tools to vet and communicate the quality of a crate and its supply-chain, like community-curated or even additional org-maintained crates, and maybe a handful delivered precompiled in the default rustup distribution which can change over time. I don't think they need to be added to std itself though

kibwen 6 hours ago||
The idea that Rust has a small standard library is a weird meme. Rust has an enormous standard library. Look at any Rust release and you'll see dozens of new library APIs added, and consider that Rust has about nine releases a year, meaning that Rust adds over a hundred APIs per year, and has consistently for the past ten years. Rust frequently adds things that obviate popular crates, most recently the cfg_if crate was made redundant by the new cfg_select macro. And half of every dependency graph that people wrong their hands over are actually first-party external crates provided by either the Rust organization itself or by known contributors to the project. When people say that Rust has a small standard library, mostly they seem to just mean that it doesn't include a webserver.
bel8 5 hours ago||
It still lacks basic functionality like a JSON parser, regex, directory walker, rnd generator and cli arg parsing.

I won't mention lack of date/time lib because that's complex and changes often.

That's why projects end up with 100s of crates, sometimes 1000s.

This might not be a well received fact in Rust community, but it's a fact nonetheless.

bilkow 3 hours ago||
My personal opinion on each of those:

JSON: there are a ton of different ways to do serialization and deserialization, each with their own tradeoffs, and serde (the most popular) is far from universally agreed upon. The same goes for JSON specifically, there are many different serialization formats with different tradeoffs.

regex: Owned by the rust-lang organization already. You get the benefits of trust (if you trust std, you trust the rust-lang organization anyway), but without the issues of being in std (backwards compatibility and bloat). The only problem I see with that is that BurntSushi is still the owner of the package and as such can still publish new versions on his own (AFAIK crates.io currently requires at least one user owner, but that's something that can be solved by improving crates.io permissions).

walkdir: It has been been postponed, due to the complexity of WalkDir, but may be added in the future. I agree this should be in std. https://web.archive.org/web/20260820171531/https://github.co...

RNG: rand is still evolving, with breaking changes half a year ago. Preferred generators tend to change over time, so I don't see those getting into std (remember, it has to be maintained forever!). I could see the interface (traits) getting into std, but I see no advantage to it: it's maintained by rust-random, but even if you wanted it to be maintained by the same authors as the Rust language (let's say you trust them more than rust-random), you could just move it back to rust-lang-nursery or rust-lang.

CLI arg parsing: not simple at all! The community's preferred solution has 70kLOC (with support for so many features), but there's also argh, pico-args, and others, each with their own tradeoffs.

> That's why projects end up with 100s of crates, sometimes 1000s.

Also because libraries are split up in many crates. For example, regex is split in 3 crates: regex, regex-syntax and regex-automata, and depends on other crates from the same author, such as aho-corasick.

All that said, there are many crates, such as algorithms like aho-corasick, that I think could me moved into the rust-lang org, like regex was.

See also: https://home.expurple.me/posts/a-big-standard-library-is-ove...

christophilus 7 hours ago||
Rust seems barely better than Node in this regard. Go or .Net or anything with a robust standard library seems like the way to go for most projects.
ajross 6 hours ago||
Cargo (and PyPI) is undeniably better than NPM, which is just shockingly bad for cultural reasons. Yet it's not safe, and it's subject to the same class of exploit, as we're seeing.

Indeed, the solution is to get away from the wild soup of author-managed dependencies and go with something with an audited collection of software that is maintained by separate human beings from the known-vulnerable hackers writing the software.

And indeed Go and .NET and Java all qualify. But the gold standard here is Debian and all its downstreams.

nicoburns 6 hours ago||
> the solution is to get away from the wild soup of author-managed dependencies and go with something with an audited collection of software that is maintained by separate human beings from the known-vulnerable hackers writing the software.

I think we might be able to crowdsource audits. At least in the Rust ecosystem I'm confident that this is feasible with the right tooling.

rcxdude 6 hours ago||
Cargo-crev already exists if you care to use it.
nicoburns 5 hours ago||
It does, but the UX is pretty lacking compared to the regular package workflow.
silverlinex 6 hours ago||
[flagged]
fnoef 6 hours ago||
Oh, so it's not only "JavaScript bad and npm bad". Apparently, if your language uses third party dependency registry, you are prone to malicious code, regardless if it's Javascript or not.

Use containers for development. And reduce the amount of third party deps you import into your projects. This is only going to get worse.

patmorgan23 6 hours ago||
Pulling in lots of dependencies creates this kind of risk regardless of the ecosystem. That being said in the JS/NPM world you tend to have a LOT more dependencies (especially indirect ones) than other languages. I saw someone do a cursory analysis and JS/Node projects tend to have 5x the number rust or ruby projects.

This is really a cultural problem not a technical one.

frollogaston 3 hours ago|||
It's funny how left-pad was always brought up as a JS supply chain vuln when that wasn't even malware
insanitybit 6 hours ago|||
If it weren't a registry it would be ./configure scripts and makefiles. The issue is that sandboxing technology is kinda shit (especially x-plat) and languages don't build it in by default.
mabini 6 hours ago||
[flagged]
swiftcoder 6 hours ago|||
> Just wondering, whenever things go wrong with Rust - why do you all (Rust devs) point the finger at JavaScript?

I know it is almost a sport to point fingers at the "evil rust evangelists" on HN at this point, but a quick look at the fnoef's comment history would show you that they are not a rust person.

Your account, on the other hand, is a sock puppet created specifically to bitch about rust. Pot, meet kettle?

mabini 4 hours ago||
[flagged]
ux266478 6 hours ago|||
You're literally replying to someone saying npm is unfairly called out.

Rust developers aren't the ones who have problems with it. Otherwise they likely wouldn't be using Rust in the first place. I don't see anyone saying JavaScript is worse about it either, more that they're the same.

Why are you getting so defensive about it?

xdavidliu 3 hours ago||
> The genuine arrayref and append-only-vec crates are maintained by droundy, whose account appears to have been compromised.

That name looked familiar to me; I believe it's the same David Roundy who was an academic at Reed College who wrote DARCS, which is version control software. I used DARCS when I started grad school around 2010 before switching to git.

More comments...