Blogger argues Deno's permission system is not a real sandbox
A blog post on goldstein.lol sets out why its author thinks the permission system in Deno, a JavaScript runtime that reuses V8 and adds a standard library, package manager and TypeScript transpiler, is 'fundamentally insecure and misleading'. Permissions are a flagship feature, listed under 'Secure by default' on Deno's landing page. The idea is that code only reaches the outside world through the standard library, so Deno can allow or refuse each access. A command such as deno run --allow-read=/tmp/dir --allow-run=uname code.ts lets the script read one directory and run uname. A program can also ask for permissions at runtime and get a text prompt in the terminal.
The author raises two problems. The first, which the author calls the less severe one, is the prompt itself. It is plain text on stdout waiting for input on stdin. Terminals take many commands in-band, by text printed to stdout, and reply through stdin. Deno lets programs print arbitrary data and read stdin with no permissions and no filtering, so malicious code can drive the same terminal that shows the prompt. The post lists ways to abuse that: hide the prompt by changing terminal colors, trick the user into pre-feeding approval into stdin, or trick the terminal into sending approval as a reply to a request. The author includes an asciicast of the last one. The specific issue in that screencast is long patched. The terminal-colors issue was not patched as of writing; the author says it was closed in 2026 on the grounds that the prompt is 'partially visible' (an emoji shows) and 'AI agents tend to' change terminal colors, which counts as a valid use case. The author's point is that the real flaw is putting security-sensitive information on an attacker-controlled channel, and that even if every standard escape code is fixed, non-standard codes in various terminals cannot be predicted. The author contrasts sudo, which asks for a password before any other code runs.
The second problem is --allow-run. The author argues that --allow-run=uname is not a unique program identity but a shortcut for searching each directory in PATH for uname. Code can set environment variables for the child process with no extra permissions, so a script can set PATH to a directory holding a fake uname shell script that prints 'lol', and Deno runs that instead. Suppose PATH were fixed, for example by forcing it to its value at startup or requiring fully qualified paths. The author says that still fails, because most executables are dynamically linked and the dynamic loader is configured by environment variables. Passing LD_PRELOAD makes the loader load a library whose constructor runs arbitrary code; the author demonstrates it with a small C library and says it escapes the --allow-run=uname restriction. The author reports having filed this, and says Deno patched it by disallowing environment variables that start with LD_. In the author's view that fixes one case and ignores the larger issue: permission to run a single command is mostly not a useful concept, because most programs are configurable and the attacker controls their environment. The author's example is --allow-run=vim, which a user might grant to let a script open an editor. The script can then set VIMINIT to '!rm -rf /*' and delete the user's files. Patching individual ways to configure programs is not the solution, the author says; the solution is to sandbox all the code, not just the JavaScript.
The author says that in a GitHub issues discussion a Deno developer wrote: 'The main thing it protects you against is malicious code that isn't smart enough.'
In the conclusions the author says Deno tries to do what the operating system should do, emulating syscall filtering by filtering standard library calls, and that this breaks down as soon as code runs something that does not use the Deno standard library. The Deno process is 'not actually sandboxed, it only pretends it is', and the author says the other, more boring issues (for example, symlinks that lead outside the sandbox) all reduce to that. Some argue pseudo-sandboxing beats nothing, since not all malicious code is smart. The author disagrees: Deno permissions give a false sense of security and can lure someone into running untrusted code without proper sandboxing.
The author does list conditions under which Deno sandboxing might be used safely: never use more dangerous permissions like --allow-run, even with =cmd; avoid --allow-env, even --allow-env=VAR, because setting environment variables is memory unsafe and can affect libc functions; preferably run with --no-prompt so the terminal cannot be tricked; be careful about symlinks in directories granted with --allow-read or --allow-write; and accept that resource exhaustion is not covered, since zero permissions are required to burn CPU or allocate memory. Running untrusted code with no permissions in a non-interactive context, with another mechanism limiting resources, may be safe. The author still advises against it, since the path is full of footguns when untrusted code runs in a fully privileged process. The recommendation is to use a proper sandbox: 'just bwrap untrusted shit.' The post closes by asking readers not to harass Deno developers; the author calls it a technical disagreement and says the developers disagreed with the author's view.
Key facts
- The author argues the Deno process is not actually sandboxed: its permissions filter standard library calls, but the process itself is fully privileged.
- Code running under --allow-run=uname can set PATH for the child process and have a fake uname run; passing LD_PRELOAD also escaped the restriction, and Deno patched that by blocking environment variables that start with LD_.
- Permission prompts are printed to the same terminal that untrusted code can write to without permissions, so the author says it can hide the prompt or feed itself approval; a terminal-colors variant was closed in 2026 per the author.
- A Deno developer is quoted from GitHub issues as saying the system 'protects you against malicious code that isn't smart enough.'
- The author lists strict conditions for safe use, including no --allow-run or --allow-env and --no-prompt, but still recommends an OS-level sandbox such as bwrap.
Why it matters
Deno presents permissions as a headline feature under 'Secure by default', and the idea is attractive: run a script and grant it only the reads and commands it needs. If the author is right, people may use that feature as a stand-in for a real sandbox when running untrusted code, including code from the packages and scripts they pull in. The post's central point is a design critique rather than a single bug: filtering at the standard library level breaks down the moment code runs something that does not use the Deno standard library, such as a child process.
Who it affects
Developers who run untrusted or third-party code under Deno and lean on flags such as --allow-run, --allow-env or the runtime permission prompts. Also anyone building a tool around Deno permissions for isolation. The author also mentions that AI agents tend to change terminal colors, which was given as a reason to close the terminal-colors issue, so tooling that drives a terminal comes into the picture too.
How to use it
The author's advice is to put untrusted code in a proper OS-level sandbox and names bwrap: 'just bwrap untrusted shit.' If you do use Deno permissions anyway, the post lists conditions: never use --allow-run, even with a specific command; avoid --allow-env, even for one variable; run with --no-prompt so the terminal cannot be tricked; be careful about symlinks inside directories granted for reading or writing; and do not rely on permissions to limit CPU or memory, which need none. Running code with no permissions at all in a non-interactive setting, with resource use controlled some other way, may be safe, but the author still does not recommend it.
How solid is it
This is one author's opinion essay, backed by short code demonstrations. The PATH trick is shown with a fake uname script that prints 'lol', and the LD_PRELOAD escape with a small C library. The author says Deno patched the LD_ case and that the specific screencast issue is long patched. The terminal-colors prompt-hiding report was, per the author, closed in 2026. Beyond one unnamed Deno developer's remark in GitHub issues, the post gives no official Deno statement. It names no CVEs, issue numbers or Deno versions, and does not compare Deno with other runtimes.
Risks and caveats
The post is a critique from one person who says outright that this is a technical disagreement with the Deno developers, who disagreed with the author's view. The author concedes that some malicious code is not smart enough to get around the permissions and that safe use is possible under narrow conditions. The post does not say that any real-world attack using these issues has happened. Several named issues have been patched, so the current state of Deno may differ from the examples. Readers should not treat the claim that Deno gives no protection as established fact; it is the author's argument, and the author also asks readers not to harass Deno developers over it.
“The main thing it protects you against is malicious code that isn't smart enough.”
— A Deno developer (unnamed), in GitHub issues, as quoted in the blog post