Deno --allow-net host allow-list does not restrict server bind address
0 reputation · 09 May 2020, 23:32 UTC
0 reputation · 09 May 2020, 23:32 UTC
Deno's --allow-net flag accepts an optional comma-separated host:port allow-list (since v1.9) that restricts which remote addresses a process may connect to or accept connections from. However, the flag does not validate or constrain the address passed to Deno.listen(). A server can bind to 0.0.0.0:8000 while running with --allow-net=127.0.0.1:8000; the process starts successfully, but inbound connections from non-localhost sources are rejected at the syscall layer.
This separation between bind-time and connect-time checks creates a configuration gap: the listen address is effectively unvalidated, so a typo or copy-paste error in the bind string does not produce a permission error at startup. The documentation recommends binding to 127.0.0.1 explicitly, but that remains a convention rather than an enforced constraint. There is also no runtime API to inspect the effective network permission set after startup.
What are the intended threat-model assumptions behind allowing a bind address outside the allow-list? Are there plans to add a startup validation that warns or errors when Deno.listen() is called with an address not covered by the active --allow-net host list? Can the permission prompt (--prompt) be made to trigger at bind time instead of first connection?
30275 reputation · 10 May 2020, 03:39 UTC
--allow-net is enforced on remote operations, not on bind. A process can call Deno.listen({ hostname: "0.0.0.0", port: 8000 }) with --allow-net=127.0.0.1:8000 and start without a permission error. The allow-list is checked when a socket connects outbound or when an inbound connection is accepted, not when the socket is bound. The --prompt prompt therefore appears on first connect/accept, not at bind time.
As of the Deno 1.x series up to v1.42 there is no implemented startup validation that warns or errors when Deno.listen() is called with an address outside the active --allow-net list, and no accepted proposal to add such a check is documented. Changing the prompt to trigger on bind would require a change to the permission API and is not currently planned or documented.
The permission model treats binding to a local interface as harmless. The intended control is to prevent unwanted remote communication, not to restrict which local addresses a program may listen on. Under this model the OS network stack is assumed to be the enforcement point for which packets reach the process; permission checks gate the accept of remote peers that match the allow-list.
This creates the configuration gap you describe: a typo or copy-paste error in the bind string does not produce a permission error at startup, and the effective exposure depends on OS firewalling and the chosen bind address.
deno run --allow-net=127.0.0.1:8000 your_script.ts where the script calls Deno.listen({ hostname: "0.0.0.0", port: 8000 }). The process should start without error.curl http://127.0.0.1:8000. The connection should succeed if the handler is reachable.--prompt and observe that the permission prompt appears only on first inbound accept or outbound connect, not when Deno.listen() is called.Cautions: relying on bind address to enforce network restrictions is unsafe; a mis-configured bind will not produce a permission error at startup and may allow unintended exposure if the OS firewall is misconfigured. Future Deno releases could modify the permission model; current behavior may change without notice.
To give a version-specific recommendation, what Deno version and edition are you running? Behavior and planned changes are version dependent.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.