Keep the built-in allowlist to what the sandbox itself needs #76

Merged
branderson merged 1 commits from allowlist-trim into main 2026-08-05 02:04:35 -07:00
Owner

Summary generated by LLM agent

Third of three, alongside #74 and #75, and independent of both — it branches
from main and touches different files.

Restore commands, first, because they are the point

If you rely on any of these, run one of these on the host and nothing changes
for you:

dejima-allow --global gitlab.com
dejima-allow --global pypi.org
dejima-allow --global files.pythonhosted.org
dejima-allow --global proxy.golang.org
dejima-allow --global sum.golang.org

(One domain per invocation.) That restores the previous behaviour exactly, as
an approval you made rather than a default you inherited. A project that needs
one can instead put it in .dejima/allowed-domains, where it is reviewed with
the project.

What changed and why

The built-in list is the one grant with no review anywhere in it: every name
on it is reachable from every sandbox on the host, for every project, whether
or not that project has any use for it. That makes it the place where
"individually reasonable" compounds into a standing grant nobody agreed to.

Five entries were editor and language tooling rather than sandbox machinery —
gitlab.com, pypi.org, files.pythonhosted.org (mason's Python LSP
downloads), proxy.golang.org and sum.golang.org.

What remains is what the sandbox cannot run without:

  • registry.npmjs.org and platform.claude.com — the harness and its updates
  • release-assets.githubusercontent.com — where baked-in tooling fetches
    binaries
  • api.anthropic.com, under its existing proxy-off condition, unchanged

release-assets.githubusercontent.com is the arguable one and I kept it. By
origin it is the same editor-tooling bucket as the rest, but it is also where
an ordinary npm postinstall gets its prebuilt binary — removing it breaks a
far wider class of routine work than the other four, for a much smaller
reduction. Say the word and it goes.

This connects to #74/#75 rather than being housekeeping: a hardened CI runner
reads its egress allowlist from .dejima/allowed-domains on main, so the
approval route is now also the route by which a destination becomes reachable
from CI. A name granted by being built in is a name that never appears in any
diff, in either place.

The Dockerfile still ships the Go toolchain, and now says plainly that
shipping it is not the same decision as granting every sandbox on the host
reach to its module proxy.

Tests

  • test/static.bats gains a guard that no language package host is built in.
    It lists crates.io and rubygems.org alongside the five removed, because
    the failure mode here is growth by reasonable-looking addition, one entry at
    a time.
  • test/runtime.bats's ipset-refresh test moves from pypi.org to
    registry.npmjs.org. It needs a name that is built in — that is the
    property it exercises — so it would have failed on this change, correctly.

bats test/static.bats (163), test/config.bats and test/proxy.bats all
clean. The host-docker half was not run locally; a sandbox has no Docker by
design, and that is the suite carrying the one edit I could not execute here.

**Summary generated by LLM agent** Third of three, alongside #74 and #75, and independent of both — it branches from `main` and touches different files. ## Restore commands, first, because they are the point If you rely on any of these, run one of these on the host and nothing changes for you: ```sh dejima-allow --global gitlab.com dejima-allow --global pypi.org dejima-allow --global files.pythonhosted.org dejima-allow --global proxy.golang.org dejima-allow --global sum.golang.org ``` (One domain per invocation.) That restores the previous behaviour exactly, as an approval you made rather than a default you inherited. A project that needs one can instead put it in `.dejima/allowed-domains`, where it is reviewed with the project. ## What changed and why The built-in list is the one grant with no review anywhere in it: every name on it is reachable from every sandbox on the host, for every project, whether or not that project has any use for it. That makes it the place where "individually reasonable" compounds into a standing grant nobody agreed to. Five entries were editor and language tooling rather than sandbox machinery — `gitlab.com`, `pypi.org`, `files.pythonhosted.org` (mason's Python LSP downloads), `proxy.golang.org` and `sum.golang.org`. What remains is what the sandbox cannot run without: - `registry.npmjs.org` and `platform.claude.com` — the harness and its updates - `release-assets.githubusercontent.com` — where baked-in tooling fetches binaries - `api.anthropic.com`, under its existing proxy-off condition, unchanged `release-assets.githubusercontent.com` is the arguable one and I kept it. By origin it is the same editor-tooling bucket as the rest, but it is also where an ordinary npm postinstall gets its prebuilt binary — removing it breaks a far wider class of routine work than the other four, for a much smaller reduction. Say the word and it goes. This connects to #74/#75 rather than being housekeeping: a hardened CI runner reads its egress allowlist from `.dejima/allowed-domains` on `main`, so the approval route is now also the route by which a destination becomes reachable from CI. A name granted by being built in is a name that never appears in any diff, in either place. The Dockerfile still ships the Go toolchain, and now says plainly that shipping it is not the same decision as granting every sandbox on the host reach to its module proxy. ## Tests - `test/static.bats` gains a guard that no language package host is built in. It lists `crates.io` and `rubygems.org` alongside the five removed, because the failure mode here is growth by reasonable-looking addition, one entry at a time. - `test/runtime.bats`'s ipset-refresh test moves from `pypi.org` to `registry.npmjs.org`. It needs a name that is built in — that is the property it exercises — so it would have failed on this change, correctly. `bats test/static.bats` (163), `test/config.bats` and `test/proxy.bats` all clean. The `host-docker` half was not run locally; a sandbox has no Docker by design, and that is the suite carrying the one edit I could not execute here.
branderson added 1 commit 2026-08-04 23:57:18 -07:00
firewall: keep the built-in allowlist to what the sandbox itself needs
tests / sandbox (proxy) (pull_request) Successful in 2m5s
tests / sandbox (static) (pull_request) Successful in 2m47s
tests / sandbox (providers) (pull_request) Successful in 4m6s
tests / sandbox (remote) (pull_request) Successful in 4m51s
tests / sandbox (project) (pull_request) Successful in 5m24s
tests / sandbox (config) (pull_request) Successful in 5m31s
tests / sandbox (audit) (pull_request) Successful in 7m40s
tests / host-docker (pull_request) Successful in 5m31s
5c30839ff8
The built-in list grants to every sandbox on the host, for every project, with
no review anywhere. That makes it the one place where "this seems reasonable"
compounds: each entry is individually defensible and the total is a standing
grant nobody agreed to per project.

Five entries were tooling rather than sandbox machinery - gitlab.com, pypi.org,
files.pythonhosted.org, proxy.golang.org and sum.golang.org, which between them
serve mason's Python LSP downloads and the Go module proxy. What remains is
what the sandbox cannot run without: registry.npmjs.org and platform.claude.com
for the harness and its updates, release-assets.githubusercontent.com for the
binaries baked-in tooling fetches, and api.anthropic.com under its existing
proxy-off condition.

release-assets.githubusercontent.com is the arguable one and it stays. It is
the same editor-tooling bucket by origin, but it is also where an ordinary npm
postinstall gets its prebuilt binary, so removing it breaks a much wider class
of routine work than the other four.

Nothing is lost, only moved to where it gets reviewed: `dejima-allow --global
<domain>` restores any of these permanently, and a project that needs one says
so in .dejima/allowed-domains, which is read with the project. That route now
matters more than it did - a hardened CI runner reads its egress allowlist
from that same file on main (docs/ci.md), so a name granted by being built in
is a name that never appears in any diff.

The Dockerfile still ships the Go toolchain and says plainly that shipping it
is not the same decision as granting every sandbox reach to its module proxy.

runtime.bats's ipset-refresh test moves off pypi.org onto registry.npmjs.org:
it needs a name that is built in, since that is the property it exercises.
static.bats gains a guard that no language package host is built in, listing
crates.io and rubygems.org alongside the removed five - the failure mode here
is growth by reasonable-looking addition, and that is what it is there to
catch.
branderson merged commit 1ca2ca4466 into main 2026-08-05 02:04:35 -07:00
Sign in to join this conversation.