I’m not a fan of Deno’s security model (2024)
46 points by ThinkChaos
46 points by ThinkChaos
Java since its inception had similar concept of Security Manager, which was eventually deprecated and removed: https://openjdk.org/jeps/411
I think it was "broken by design" similarly to the Deno's case.
Good article; though regarding the sudo example - most people's sudo is not really secure in any way:
echo "alias sudo='sudo echo pwned && sudo'" >> ~/.bashrc
Is probably a way you can get privesc on >90% of desktop users. Not that it matters since you can access saved cookies and passwords without root anyway.
that is true, but it’s more of a general problem with everyones security-sensitive settings being stored in a writeable place. sudo could do better though, by showing you what command you are running when asking for credentials.
aside: I’m really annoyed that run0, which is mostly reasonable, prints the action it asks authentication for as
Authentication is required to start transient unit 'run-p695148-i710731.service'.
which is completely useless. it almost fixed most of the problems with sudo, and then decided to leak implementation details in this particular spot.
author here, did not expect this to surface after so much time lol. I guess it doesn’t matter much anymore, since deno will probably be dead soon, but it was weird while it lasted.
Oh hi! I didn't realize you were on here!
I found this post via looking up information about Rust specialization, which lead me to read your stable specialization in Rust article. I liked that post so decided to check what other interesting things your blog might have :)
The Deno one still seems relevant to me since as a non Deno user, I never actually thought much about their security API, and assumed it was good. Knowing about those pitfalls will help with future designs and decisions.
Last I heard it still has an active fork which is pulling out all the node compat and going back to the basics.
Honestly I think being set free from its company will prove good for it, because node compat was a "let's cash in" move, not one that made sense given the project's own vision. I'm not the first person to point this out either, but I very much agree with others who have.
Recommending bwrap at the bottom just reminds me that bwrap has no easy or obvious way to sandbox processes either.
https://man.archlinux.org/man/bwrap.1
I know a fair bit about linux, and idk how to use that interface to sandbox stuff properly.
The interface for Jart's pledge tool is much easier to understand (tho idk how safe it is either)
bwrap doesn't give you a one-liner, but a vertical scan through that manpage should allow you to construct something reasonable. For example, the following works fine:
$ bwrap \
--unshare-all \
--share-net \
--die-with-parent \
--proc /proc \
--dev /dev \
--tmpfs /tmp \
--ro-bind /bin /bin \
--ro-bind /usr/bin /usr/bin \
--ro-bind /lib /lib \
--ro-bind /lib64 /lib64 \
--ro-bind /usr/lib /usr/lib \
--ro-bind /usr/lib64 /usr/lib64 \
/bin/bash -l
bash-5.3$ id
uid=1000 gid=1001 groups=1001,65534
bash-5.3$
EDIT: yes, it's a mouthful, but anything more specific becomes opinionated, and bwrap tries to be unopinionated. Writing an opinionated sandboxing tool on top of bwrap would essentially be about the above in terms of lines of code, plus whatever configuration you want to expose.
That's not safe because you're not blocking the TIOCSTI syscall or using --new-session.
It also won't fail-safe when userns or cgroups are unavailable.
Which is kind of my point. It's hard to know how to use this safely. I don't know if I missed anything else, or about how much that config would let a malicious process exfiltrate about my system, etc.
Very good points. Luckily it seems I am vulnerable to none of the things you mention, because in the two usages I have of bwrap, in one I block TIOCSTI separately with seccomp, and in the other I'm using --new-session. Furthermore I use new, stock kernels so I guess (?) I don't have to worry about cgroups or userns not being available (though I will change them to use the non-try flags...).
This does beg the question how the f one sandboxes on Linux. Which is also your point, I think.
Given all this, I'd suggest rephrasing the suggestion to 'just bwrap' stuff, because unfortunately it's not that simple.
The idea that "the real issue is using an attacker-controlled channel for security" kind of opened my mind. I never thought about the terminal as being "attacker controlled". If I wanted to understand that thinking better, does anybody have any suggestions for what could explain it to me?
It is unfortunate that Deno specifically declined to pursue a capability based security model, which would have moved the needle.
But who are we kidding? It's JavaScript/TypesScript, security and correctness are not core value in this ecosystem. I'm hoping AI can make high assurance languages feasible and ergonomic. Until then, I'm staying out of the security world.
It's JavaScript/TypesScript, security and correctness are not core value in this ecosystem.
I sort of disagree with this. JavaScript is the only truly sand-boxable language (language not runtime) with widespread use.
Java is an incredible success, but it has proven (repeatedly) to not be sand-boxable. Portable? Yes. Secure? Nope.
For background: I was one of the designers of Ecstasy, which is a zero privilege language, with capabilities injected. In retrospect, I probably should have just used JavaScript, but I just couldn't stomach it.
It's famously been used to implement some core capability based security models. But it's a retrofit at best and not having runtime enforced types is ... the bare minimum. Wanna do high assurance JavaScript? You start by extending null to prevent pollution up the prototype chain. And then you reimplement a dynamic type system. It's a mess.
Working wtih Haxe really opened my eyes to how much benefit can be had from putting more than a week worth of effort into the upfront design. Now with immutability, contracts ... let JavaScript be the mid 90's era scripting language it was designed to be. I think it's time to move on and invest in new ecosystems instead of pushing JS/Python/PHP further beyond their design tolerances.
Does Haxe support capability-based security? I'm not familiar with the language but I wasn't able to find discussion about that.
JS has https://hardenedjs.org/; does Haxe have anything similar?
I've heard of Haxe before but never had a chance to really look at it. I looked at it this morning and it looks like a great project! Does it do capabilities? I didn't see anything about that in the feature list.
The way we designed for capabilities is that the only thing that code can do (i.e. what's in the IR) is declare and assign local variables, loop, new objects, call methods/functions, etc. Even all of what you'd normally think of as built in language functionality (e.g. adding two numbers) is represented as methods/functions in the language. In other words, it's a super restricted IR with zero access to the outside world. So obviously it eliminates stuff like buffer overflows by design, but it also eliminates any attacks on the shell, any attacks on the hardware, the OS itself, any libraries, the disk, etc. The language doesn't even have access to a console or the clock.
So in theory the only two remaining attack vectors at the language level are (i) CPU denial of service e.g. infinite loops and (ii) memory denial of service e.g. purposeful exhaustion of memory. The runtime (e.g. the JIT) is responsible for managing both of these.
The flip side of that is that very few apps can do anything of value without access to files, a clock, a console, the network, etc. So applications and libraries that need access to a clock (for example) need to indicate that dependency via an injection of a clock. Only abstract interfaces (no idea what's behind it) and constant values can be injected, meaning that even when you have a clock, you have no idea if it's a mock, or a real time clock, or fuzzed clock, or ...
The same goes for any hardware / OS resource that an application needs to do its work.