Summarizer

Package manager alternatives

Discussion of whether package managers are fundamentally flawed, with references to Odin language's no-package-manager philosophy and Go's vendoring approach

← Back to Axios compromised on NPM – Malicious versions drop remote access trojan

The discussion reveals a deep skepticism toward modern package managers like NPM, which are frequently criticized for enabling supply chain attacks through post-install scripts and massive, unvetted transitive dependency trees. Proponents of alternatives advocate for "vendoring"—the practice of copying source code directly into a project—as a way to ensure long-term stability and offline reliability, echoing the minimalist, no-package-manager philosophy seen in the Odin language. While some argue that automation is an inescapable necessity for modern development, others contend that high-quality, single-file libraries like SQLite prove that powerful code can be distributed safely without complex registries. Ultimately, the consensus suggests that if package managers are to survive, they must evolve to incorporate manifest-based permissions, 2FA mandates, and sandboxed execution environments to mitigate the risks of blindly trusting third-party code.

59 comments tagged with this topic

View on HN · Topics
Personally I've heard Odin [1] to do a decent job with this, at least from what I've superficially learned about its stdlib and included modules as an "outsider" (not a regular user). It appears to have things like support for e.g. image file formats built-in, and new things are somewhat liberally getting added to core if they prove practically useful, since there isn't a package manager in the traditional sense. Here's a blog post by the language author literally named "Package Managers are Evil" [2] (Please do correct me if this is wrong, again, I don't have the experience myself.) [1] https://pkg.odin-lang.org/ [2] https://www.gingerbill.org/article/2025/09/08/package-manage...
View on HN · Topics
> they just move slower so it’s not as attractive of a target. Well, there’s other things. Maven doesn’t allow you to declare “version >= x.y.z” and doesn’t run arbitrary scripts upon pulling dependencies, for one thing. The Java classpath doesn’t make it possible to have multiple versions of the same library at the same time. That helps a lot too. NPM and the way node does dependency management just isn’t great. Never has been.
View on HN · Topics
The other thing that keeps coming up is the github-code-is-fine-but-the-release-artifact-is-a-trojan issue. It really makes me question if "packages" should even exist in JavaScript, or if we could just be importing standard plain source code from a git repo. I understand why this doesn't work well with legacy projects, but it's something that the language could strive towards.
View on HN · Topics
> I understand why this doesn't work well with legacy projects, but it's something that the language could strive towards. Why wouldn't that work well with legacy projects? In fact, the projects I was a part of that I'd call legacy nowadays, was in fact built by copy-and-pasting .js libraries into a "vendor/" directory, and that's how we shipped it as well, this was in the days before Bower (which was the npm of frontend development back in the day), vendoring JS libs was standard practice, before package managers became used in frontend development too. Not sure why it wouldn't work, JavaScript is a very moldable language, you can make most things work one way or another :)(
View on HN · Topics
This might make things worse not better. Yes - the postinstall hook attack vector goes away. You can do SHA pinning since Git's content addressing means that SHA is the hash of the content. But then your "lockfile" equivalent is just... a list of commit SHAs scattered across import statements in your source? Managing that across a real dependency tree becomes a nightmare. This is basically what Deno's import maps tried to solve, and what they ended up with looked a lot like a package registry again. At least npm packages have checksums and a registry that can yank things.
View on HN · Topics
You can just git submodule in the dependencies. Super easy. Also makes it straightforward to develop patches to send upstream from within your project. Or to replace a dependency with a private fork. In my experience, this works great for libraries internal to an organization (UI components, custom file formats, API type definitions, etc.). I don't see why it wouldn't also work for managing public dependencies. Plus it's ecosystem-agnostic. Git submodules work just as well for JS as they do for Go, sample data/binary assets, or whatever other dependencies you need to manage.
View on HN · Topics
or you don't use a package manager where anyone can just publish a package (i.e. use your system package manager). There is still some risk, but it is much smaller. Like, if xz were distributed by PyPI or NPM, everyone would have been pwned, but instead it was (barely) found. It's true that system repos doesn't include everything, but you can create your own repositories if you really need to for a few things. In practice Fedora/EPEL are basically sufficient for my needs. Right now I'm deploying something with yocto, which is a bit more limited in slection, but it's pretty easy to add my own packages and it at least has hashes so things don't get replaced without me noticing (to be fair, I don't know if the security practices of open-embedded recipes are as strong as Fedora...).
View on HN · Topics
Kinda. With Bun I use less dependencies from NPM than I used from Nuget with .NET to build minimal apis. For example the pg driver.
View on HN · Topics
> Another layer of AI tooling is the cost of spinning up your own version of some libraries is lowered and can be made hyper specific to your needs rather than pulling in a whole library with features you'll never use. Tell me about it. Using AI Chatbots (not even agents), I got a MVP of a packaging system[1] to my liking (to create packages for a proprietary ERP system) and an endpoint-API-testing tool, neither of which require a venv or similar to run. ------------------------------ [1] Okay, all it does now is create, sign, verify and unpack packages. There's a roadmap file for package distribution, which is a different problem.
View on HN · Topics
So, youre on Microsoft then, judging by ScottPlot you write .NET desktop apps. If you use Dapper, you probably use Microsoft.Data.SqlClient, which is... distributed over NuGet and vulnerable to supply chain attack. You may not need many deps as a desktop dev. Modern day line of business apps require a lot more deps. CSVHelper, ClosedXML, AutoMapper, WebOptimizer, NetEscapades.AspNetCore.SecurityHeaders. Yes less deps people need the better but it doesn't fix trhe core problem. Sharing and distrib uting code is a key tenant of being able to write modern code.
View on HN · Topics
Go didn't even have versioning for dependencies for ages, so CVE reporting was a disaster. And there's plenty of libraries you'll have to pull to get a viable product.
View on HN · Topics
Or find the best third party library and copy the code from a widely used version that has been out long enough to have been well tested into your source tree. The problem is not third party libraries. It is updating third party libraries when the version you have still works fine for your needs.
View on HN · Topics
Don't do this. Use a package manager that let's you specify a specific version to pin against. Vendoring side steps most automated tooling that can warn you about vulnerabilities. Vendoring is a signal that your tooling is insufficient, 99% of the time.
View on HN · Topics
Vendoring means you don't have to fetch the internet for every build, that you can work offline, that you're not at the mercy of the oh-so-close-99.999 availability, that it will keep on working in 10 years, and probably other advantages. If your tooling can pull a dependency from the internet, it could certainly check if more recent version from a vendored one is available.
View on HN · Topics
Is there any package manager incapable of working offline?
View on HN · Topics
> Is there any package manager incapable of working offline? I think you've identified the problem here: package management and package distribution are two different problems. Both tools have possibilities for exploits, but if they are separate tools then the surface area is smaller. I'm thinking that the package distribution tool maintains a local system cache of packages, using keys/webrings/whatever to verify provenance, while the package management tool allows pinning, minver/maxver, etc.
View on HN · Topics
> PSA: npm/bun/pnpm/uv now all support setting a minimum release age for packages. The solution is not moar toolz. That's the problem—this crazy mindset that the problems endemic to bad tooling have a solution in the form of complementing them with another layer, rather than fewer. Git and every sane SCM already allow you to manage your source tree without jumping through a bunch of hoops to go along with wacky overlay version control systems like the one that the npmjs.com crew designed, centering around package.json as a way to do an end-run around Git. You don't need to install and deploy anything containing never-before-seen updates just because the NodeJS influencer–developers say that lockfiles are the Right Way to do things. (It's not.) Opting in to being vulnerable to supply chain attacks is a choice. < https://news.ycombinator.com/item?id=46006471 > < https://news.ycombinator.com/item?id=46360308 >
View on HN · Topics
There are many options. Here's a post just briefly listing a few of the ones that would be handled by package managers and registries, but there are also many things that would be best done in CI pipelines as well. https://news.ycombinator.com/item?id=47586241
View on HN · Topics
An alternative: - copy the dependencies' tests into your own tests - copy the code in to your codebase as a library using the same review process you would for code from your own team - treat updates to the library in the same way you would for updates to your own code Apparently, this extra work will now not be a problem, because we have AI making us 10x more efficient. To be honest, even without AI, we should've been doing this from the start, even if I understand why we haven't. The excuses are starting to wear thin though.
View on HN · Topics
NPM only gained minimum package age in February of this year , and still doesn't support package exclusions for internal packages. https://github.com/npm/cli/pull/8965 https://github.com/npm/cli/issues/8994 Its good that that they finally got there but.... I would be avoiding npm itself on principle in the JS ecosystem. Use a package manager that has a history of actually caring about these issues in a timely manner.
View on HN · Topics
I suppose you would have to commit your node_modules, or otherwise cache your setup so that all prerequesite modules are built and ready to install without running post-install scripts?
View on HN · Topics
Essential steps to minimise your exposure to NPM supply chain attacks: — Run Yarn in zero-installs mode (or equivalent for your package manager). Every new or changed dependency gets checked in. — Disable post-install scripts. If you don’t, at least make sure your package manager prompts for scripts during install, in which case you stop and look at what it’s going to run. — If third-party code runs in development, including post-install scripts, try your best to make sure it happens in a VM/container. — Vet every package you add. Popularity is a plus, recent commit time is a minus: if you have this but not that, keep your eyes peeled. Skim through the code on NPM (they will probably never stop labelling it as “beta”), commit history and changelog. — Vet its dependency tree. Dependencies is a vector for attack on you and your users, and any new developer in the tree is another person you’re trusting to not be malicious and to take all of the above measures, too.
View on HN · Topics
Zero-installs mode does not replace the lockfile. Your lockfile is still the source of truth regarding integrity hashes. However, it’s an extra line of defence against 1) your registry being down (preventing you from pushing a security hotfix when you find out another package compromised your product), 2) package unpublishing attacks (your install step fails or asks you to pick a replacement version, what do you do at 5pm on a Friday?), and 3) possibly (but haven’t looked in depth) lockfile poisoning attacks, by making them more complicated. Also, it makes the size of your dependency graph (or changes therein) much more tangible and obvious, compared to some lines in a lockfile.
View on HN · Topics
Good points. But what do you mean with 3: "lockfile poisoning attacks, by making them more complicated" — making the lockfiles more complicated ? Also, 4) Simpler to `git diff` the changes, when you have the source locally already :- )
View on HN · Topics
Number 1 would only be a win for zero-installs if it happened that registry was up when you made the security hotfix, since you'd need to install the depdencency the first time to get it in VC, but then suddenly down when doing a deploy. Seems like a highly unlikely scenario to me. Also, cases where npm CVEs must be patched with such urgency or bad things will happen are luckily very rare, in my experience. Most npm CVEs are stuff like DDoS vulnerabilities, and you should have mitigations for those in place for at the infra-level anyway (e.g. request timeouts, rate limits, etc), or you are pretty much guaranteed to be cooked sooner or later anyway. The really dangerous stuff like arbitrary command execution from a library that takes end user input is much much more rare. The most recent big one I remember is React2shell. Number 2 hasn't been much of an issue for a long time. npm doesn't allow unpublishing package after 72 hours (apart from under certain rare conditions). Don't know about number 3. Would feel to me that if you have something running that can modify lockfile, they can probably also modify the chekced-in tars. I can see how zero-installs are useful under some specific constraints where you want to minimize dependencies to external services, e.g. when your CI runs under strict firewalls. But for most, nah, not worth it.
View on HN · Topics
> you'd need to install the depdencency the first time to get it in VC, but then suddenly down when doing a deploy. Which dependency? It sounds like you are assuming some specific scenario, whereas the fix can take many forms. In immediate term, the quickest step could be to simply disable some feature. A later step may be vendoring in a safe implementation. The registry doesn’t need to be actually down for you , either; the necessary condition is that your CI infrastructure can’t reach it. > cases where npm CVEs must be patched with such urgency or bad things will happen are luckily very rare, in my experience. Not sure what you mean by “npm CVEs”. The registry? The CLI tool? As I wrote, if you are running compromised software in production, you want to fix it ASAP. In first moments you may not even know whether bad things will happen or not, just that you are shipping malicious code to your users. Even if you are lucky enough to determine with 100% confidence (putting your job on the line) that the compromise is inconsequential, you don’t want to keep shipping that code for another hour because your install step fails due to a random CI infra hiccup making registry inaccessible (as happened in my experience at least half dozen times in years prior, though luckily not in a circumstance where someone attempted to push an urgent security fix). Now imagine it’s not a random hiccup but part of a coordinated targeted attack, and somehow it becomes something anticipated. > Number 2 hasn't been much of an issue for a long time. npm doesn't allow unpublishing package after 72 hours (apart from under certain rare conditions). Those rare conditions exist. Also, you are making it sound as if the registry is infallible, and no humans and/or LLMs there accept untrusted input from their environment. The key aspect of modern package managers, when used correctly, is that even when the registry is compromised you are fine as long as integrity check crypto holds up and you hold on to your pre-compromise dependency tree. The latter is not a technical problem but a human problem, because conditions can be engineered in which something may slip past your eyes. If this slip-up can be avoided at little to no cost—in fact, with benefits, since zero-installs shortens CI times, and therefore time-to-fix, due to dramatically shorter or fully eliminated install step—it should be a complete no-brainer. > Don't know about number 3. Would feel to me that if you have something running that can modify lockfile, they can probably also modify the chekced-in tars. As I wrote, I suspect it’d complicate such attacks or make them easier to spot, not make them impossible.
View on HN · Topics
This is why Artifactory and similar exist and they do this better. You ~never want to vendor libraries.
View on HN · Topics
Are you saying it replaces my package manager, or that I should add another tool to my stack, vet yet another vulnerable dependency for critical use, to do something my package manager already does just as well? > You ~never want to vendor libraries. I just explained why you should, and you are yet to provide a counter-argument.
View on HN · Topics
Exactly. Yarn uses a yarn.lock file with the sha256 hashes of each npm package it downloads from the repo (they are .tgz files). If the hash won't match, install fails. No need to commit the dependencies into your git.
View on HN · Topics
Package managers are a failed experiment. We have libraries like SQLite, which is a single .c file that you drag into your project and it immediately does a ton of incredibly useful, non-trivial work for you, while barely increasing your executable's size. The issue is not dependencies themselves, it's transitive ones. Nobody installs left-pad or is-even-number directly, and "libraries" like these are the vast majority of the attack surface. If you get rid of transitive dependencies, you get rid of the need of a package manager, as installing a package becomes unzipping a few files into a vendor/ folder. There's so many C libraries like this. Off the top of my head, SQLite, FreeType, OpenSSL, libcurl, libpng/jpeg, stb everything, zlib, lua, SDL, GLFW... I do game development so I'm most familiar with the ones commonly used in game engines, but I'm sure other fields have similarly high quality C libraries. They also bindings for every language under the sun. Rust libraries are very rarely used outside of Rust, and C#/Java/JS/Python libraries are never used outside their respective language (aside form Java ones in other JVM langs).
View on HN · Topics
Package managers are now basically a requirement for language adoption. Doing it manually is not a solution, in an automated world. What is a problem is library quality. Which is downstream of nobody getting paid for it, combined with an optimistic but unrealistic "all packages are equal" philosophy. > High quality C libraries > OpenSSL OpenSSL is one of the ones where there's a ground up rewrite happening because the code quality is so terrible while being security critical. On the other end, javascript is uniquely bad because of the deployment model and difficulty of adding things to the standard library, so everything is littered with polyfills.
View on HN · Topics
> Package managers are now basically a requirement for language adoption. Doing it manually is not a solution, in an automated world. Absolute nonsense. What does automated world even mean? Even if one could infer reasonably, it's no justification. Appealing to "the real world" in lieu of any further consideration is exactly the kind of mindlessness that has led to the present state of affairs. Automation of dependency versions was never something we needed it was always a convenience, and even that's a stretch given that dependency hell is abundant in all of these systems, and now we have supply chain attacks. While everyone is welcome to do as they please, I'm going to stick to vendoring my dependencies, statically compiling, and not blindly trusting code I haven't seen before.
View on HN · Topics
> Automation of dependency versions was never something we needed How do you handle updating dependencies then?
View on HN · Topics
Relax, while mentioning the real world without any criticism for the soundness of the solution is absolute nonsense, some would say idiotic, thinking only in the absolute best solution given your narrow world view is not any better.
View on HN · Topics
While I agree that my view is narrow, the "best solution" in question is what we used to do, and it was fine. There are still many places that manually manage dependencies. Fundamentally automatic software versioning is an under-developed area in need of attention, and technologies like semantic versioning which are ubiquitous are closer to suggestions, and not true indicators of breaking changes. My personal view is that fully automatic dependency version management is an ongoing experiment and should be treated as such.
View on HN · Topics
They're not a failed experiment. No one has ever "experimented" by making a safe package manager for their new language. And it is not that insane to do so. Very basic things will get you very far: 1. Packages should carry a manifest that declares what they do at build time, just like Chrome extensions do. This manifest would then be used to configure its build environment. 2. Publishers to official registries should be forced to use 2FA. I proposed this a decade ago for crates.io and people lost their minds, like I was suggesting we drag developers to a shed to be shot. 3. Every package registry should produce a detailed audit log that contains a "who, what, when". Every build/ command should be producing audit logs that can be collected by endpoint agents too. 4. Every package registry should support TUF. 5. Typosquatting defenses should be standard. etc etc etc. Some of this is hard, some of this is not hard. All of this is possible. No one has done it, so it's way too early to say "package managers can't be made safe" when no one has tried .
View on HN · Topics
I don't understand commercial aspect of large OSS like package managers but i was wondering for years why this was missing from npm. I think typosquatting was handled by npm last year but only after some popular miss typed packages started stealing developer creds.
View on HN · Topics
The people building package managers are unaware of these problems going into it and it becomes extremely disruptive to start adding these things later on since your entire ecosystem is built on the assumption that they can do these things. It's also shockingly controversial to suggest typosquatting suggestions. I made this suggestion ages ago for cargo, demonstrated that basic distance checks would have impacted <1% of crates over all time, and people still didn't want it.
View on HN · Topics
For those who didn't know what TUF means (like me), I think they're referring to The Update Framework ( https://theupdateframework.io ).
View on HN · Topics
Sorry, I should have clarified that - you're correct. `cosign` is an example of a tool that makes this quite straightforward and proves that this sort of system can work today.
View on HN · Topics
Love these ideas!
View on HN · Topics
If you're developing for the web your attack surface is quite a bit bigger. Your proposed solution of copying a few files might work but how do you keep track of updates? You might be vulnerable to a published exploit fixed a few months ago. A package manager might tell you a new version is available. I don't know how that would work in your scenario.
View on HN · Topics
> We have libraries like SQLite, which is a single .c file that you drag into your project and it immediately does a ton of incredibly useful, non-trivial work for you, while barely increasing your executable's size. I'm not sure why you believe this is more secure than a package manager. At least with a package manager there is an opportunity for vetting. It's also trivial that it did not increase your executable's size. If your executable depends on it, it increases its effective size.
View on HN · Topics
no no, please we don't want to get back to dragging files to your project to make them work.
View on HN · Topics
And manual FTP uploads, while we're at it.
View on HN · Topics
> We have libraries like SQLite, which is a single .c file that you drag into your project You are just swapping a package manager with security by obscurity by copy pasting code into your project. It is arguably a much worse way of handling supply chain security, as now there is no way to audit your dependencies. > If you get rid of transitive dependencies, you get rid of the need of a package manager This argument makes no sense. Obviously reducing the amount of transitive dependencies is almost always a good thing, but it doesn't change the fundamental benefits of a package manager. > There's so many C libraries like this The language with the most fundamental and dangerous ways of handling memory, the language that is constantly in the news for numerous security problems even in massively popular libraries such as OpenSSL? Yes, definitely copy-paste that code in, surely nothing can go wrong. > They also bindings for every language under the sun. Rust libraries are very rarely used outside of Rust This is a WILD assumption, doing C-style bindings is actually quite common. YOu will of course then also be exposing a memory unsafe interface, as that is what you get with C. What exactly is your argument here? It feels like what you are trying to say is that we should just stop doing JS and instead all make C programs that copy paste massive libraries because that is somhow 'high quality'. This seems like a massively uninformed, one-sided and frankly ridiculous take.
View on HN · Topics
> You are just swapping a package manager with security by obscurity by copy pasting code into your project You should try writing code, and not relying on libraries for everything, it may change how you look at programming and actually ground your opinions in reality. I'm staring at company's vendor/ folder. It has ~15 libraries, all but one of which operate on trusted input (game assets). > fundamental benefits of a package manager. I literally told you why they don't matter if you write code in a sane way. > doing C-style bindings is actually quite common I know bindings for Rust libraries exist. Read the literal words you quoted. "Rust libraries are very rarely used outside of Rust". Got some counterexamples?
View on HN · Topics
https://github.com/memflow/memflow https://github.com/PyO3/pyo3 https://slint.dev/ https://github.com/dora-rs/dora It is VERY common in existing codebases that are migrating from C++/C to make heave use of FFI/ existing C
View on HN · Topics
> trusted input (game assets) Gamedev is its own weird thing, and isn't a model you want to generalize to other industries. It has to optimize for things a lot of software does not, and that skews development. Vendoring libraries is almost always a terrible idea because it immediately starts to bitrot and become a footgun. Sometimes it's necessary , but it's not desirable , and you almost always just want to pin your dependencies instead.
View on HN · Topics
I think you can do copy paste in most languages. But it will be a pain to update when there are improvements / security fixes. You got a project with 1-2 depencies? Sure. But if you need to bring in 100 different libs (because you bring in 10 libs which in turn brings in 10 libs) good luck.
View on HN · Topics
> But if you need to bring in 100 different libs (because you bring in 10 libs which in turn brings in 10 libs So don’t? With manual deps management, everyone soon gravitates to a core set of deps. And libraries developer tends to reduce their deps needs, That’s why you see most C libraries deals with file formats, protocols, and broad concerns. Smaller algorithms can be shared with gists and blog articles.
View on HN · Topics
Package managers are older than some users here. From CPAN/CTAN to ports under BSD's. Some pm's are badly maintained (Pip/NPM), while others are curated enough. Again, if you have GNU/Linux installed, install Guix, read the Info manual on 'guix import' and just create a shell/container with 'guix shell --container' (and a manifest package created from guix import) and use any crap you need for NPM in a reproducible and isolated way. You $HOME will be safe, for sure.
View on HN · Topics
Min release age might just postpone vulnerability to be applied few days later in non trivial cases like this. More I think about it, Odin lang approach of no package manager makes senses. But, for that approach won't work for Javascript as it needs npm package even for trivial things. Even vendoring approach like golang won't work with Javascript with the amount of churn and dependencies.
View on HN · Topics
Just a reminder that you can run most node things with deno run and have opt in permissions, audit trail and even external permission system integration now. The gotcha is that "deno task <<some package.json script>>" will NOT execute with this model which I find extremely unintuitive and had me thinking deno abandoned its sandbox for nodejs compatibility completely.
View on HN · Topics
How anybody is still using NPM is beyond me.
View on HN · Topics
It's reasons like this why I refuse to download Node or use anything NPM. Thankfully other languages are better anyways.
View on HN · Topics
Cargo is a great package manager and hasn't suffered from the same problems. I'll take it.
View on HN · Topics
Yet. Does cargo contain any mitigations to prevent a similar attack? Now hopefully no distro signing keys have been compromised in the latest attacks...
View on HN · Topics
The semantics are very relevant, since you presented it as a supply-chain attack. If you call a library vulnerability a supply-chain attack, then your argument has lost coherence. > The OC is somehow under the illusion... Avoiding package managers with shitty policies is the silver bullet for this attack vector. I get that it can be useful in the moment to retract published artifacts, or update them in-place, or run some code after your artifact is downloaded, but all of these are false economies in our hostile environment.