Summary
When setAllowedHosts() is used, any outbound request to a non-allowlisted host is rejected with 520 and the fixed plain-text body Origin is disallowed (from @cloudflare/containers). Sandboxed code that calls .json() on the response — the common case — crashes with an opaque parse error, and there's no supported way to customize the block response without giving up the allowlist gate entirely.
Version: @cloudflare/sandbox@0.12.1.
Repro
import requests
resp = requests.post("https://disallowed-host.example", json={})
print(resp.json())
- Node/JS runtime:
Unexpected token 'O', "Origin is disallowed" is not valid JSON
- Python runtime:
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) — body not echoed, indistinguishable from an empty response.
Both runtimes receive the same 520 "Origin is disallowed"; the difference is only how each language's JSON parser formats the decode error.
Why it's hard to handle today
In @cloudflare/containers, the allowedHosts gate runs before any outbound / outboundByHost handler and hardcodes new Response('Origin is disallowed', { status: 520 }). So the only way to return a custom (e.g. structured-JSON) block response is to drop setAllowedHosts and re-implement allow/deny inside a catch-all outbound handler — which moves the egress security gate into user code.
Request
Provide a supported way to customize the blocked-host response while keeping the allowedHosts gate — e.g. an optional onDisallowedHost(request) => Response hook, or a configurable default block response. Returning structured JSON (e.g. { "error": "host_not_allowed", "host": "..." }) would let calling code surface a clear, parseable error in every runtime.
Summary
When
setAllowedHosts()is used, any outbound request to a non-allowlisted host is rejected with520and the fixed plain-text bodyOrigin is disallowed(from@cloudflare/containers). Sandboxed code that calls.json()on the response — the common case — crashes with an opaque parse error, and there's no supported way to customize the block response without giving up the allowlist gate entirely.Version:
@cloudflare/sandbox@0.12.1.Repro
Unexpected token 'O', "Origin is disallowed" is not valid JSONjson.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)— body not echoed, indistinguishable from an empty response.Both runtimes receive the same
520 "Origin is disallowed"; the difference is only how each language's JSON parser formats the decode error.Why it's hard to handle today
In
@cloudflare/containers, theallowedHostsgate runs before anyoutbound/outboundByHosthandler and hardcodesnew Response('Origin is disallowed', { status: 520 }). So the only way to return a custom (e.g. structured-JSON) block response is to dropsetAllowedHostsand re-implement allow/deny inside a catch-alloutboundhandler — which moves the egress security gate into user code.Request
Provide a supported way to customize the blocked-host response while keeping the
allowedHostsgate — e.g. an optionalonDisallowedHost(request) => Responsehook, or a configurable default block response. Returning structured JSON (e.g.{ "error": "host_not_allowed", "host": "..." }) would let calling code surface a clear, parseable error in every runtime.