After yesterday's release of Deno with package.json support[0] some discussions about how Deno handles dependencies have been coming up again.
Since Deno's inception, I've mostly been watching it from the sidelines, dabbling a bit with it, and mostly been considering it a fad that will die out sooner or later.
Ultimately, with the new package.json support nothing really changed regarding the dependency management story of Deno. It's still as awful as ever.
Prompted by some discussions, I decided I would try to test how easy it would be to mount a typo-domain supply chain attack. And as expected, it's about as easy as buying a domain and setting up a Cloudflare Worker (which isn't any harder than setting up Deno Deploy).
And voila, for importing your favorite dependency, just copy-past the following snippet into your code (which after all is how you include dependencies in Deno):
```
import * as flat from "https://deon.land/x/flat@0.0.15/mod.ts";
```
Which is virtually indistinguishable from what you'll find here[1]:
```
import * as flat from "https://deno.land/x/flat@0.0.15/mod.ts";
```
(I swear, nothing bad will happen!)
-------
Typo supply-chain attack aren't anything new. They are probably the most popular attack type on package managers (and their registries) in the past few years. This one is just slightly different because it is even worse, because unlike a moderated[2] registry like npmjs.com, this can't be easily taken down to reduce the exposure of developers to it.
While this is just a fun little gag, the Deno teams stance on security is not so funny.
While Deno has a few minimal security options nowadays, such as subresource integrity for a deno.json, you have to actively seek them out, and most project's don't even use a deno.json.
Deno is creating a ecosystem with bad security defaults (with a community rejecting efforts towards them), to have a "simpler" system. They prioritize onboarding new developers over the security needs of the users of the services that those developers will build. I don't think that's okay.
So, go ahead and have fun: Replace deno.land with deon.land in every import you want. Deno won't stop you! :)
[0]: https://deno.com/blog/v1.31
[1]: https://deno.land/x/flat@0.0.15/mod.ts
[2]: https://docs.npmjs.com/reporting-malware-in-an-npm-package
Deno doesn't intentionally control where and how you import dependencies as long as the code in the dependency is valid and I think that's better than gatekeeping domains. Deno has permissions built-in just for this - i.e., if a dependency goes rogue, there's some level of control.
Consider node/bun on the other hand. If a dependency goes rogue, there's virtually nothing stopping it except system permissions. That's a lot worse than deno.
I think Deno tries to solve the core issue with running untrusted code (like a browser does to some extent). Dependency control can only go so far. So no complaints here.
This also gives Deno flexibility to support package.json with the same exact security guarantees. Isn't that better?