Problem
network.allowedDomains matches on host plus an optional :port. Many hosts
worth allowing are multi-tenant with the tenant in the path, so the narrowest
policy the allowlist can express is "every tenant on that host":
| What you want to allow |
What you must write |
What that actually grants |
| one object-store bucket, path-style |
storage.googleapis.com |
every public object in GCS |
| one org's container images |
ghcr.io |
every image on the registry |
| one project's Artifact Registry repo |
<region>-docker.pkg.dev |
every project in the region |
| one org's raw files |
raw.githubusercontent.com |
every public file on GitHub |
Host-scoped alternatives exist for some of these (<bucket>.s3.amazonaws.com,
<account>.blob.core.windows.net) and the allowlist handles those fine. The gap
is the path-style form, which clients don't always let you choose.
Desired state
An allowed domain can optionally be narrowed to path prefixes, expressed as a
side map keyed off an allowedDomains entry — the way deniedDomainReasons is
keyed off deniedDomains:
{
"network": {
"allowedDomains": ["storage.googleapis.com", "raw.githubusercontent.com"],
"allowedDomainPaths": {
"storage.googleapis.com": ["/my-bucket/"],
"raw.githubusercontent.com": ["/my-org/"]
}
}
}
A host absent from the map behaves exactly as it does today. A host present is
reachable only for requests under one of its prefixes.
Context
Found while hardening a sandbox configuration with a deliberately small
allowlist, where a shared object-store host had to be allowed in full to unblock
one bucket's worth of legitimate traffic.
Problem
network.allowedDomainsmatches on host plus an optional:port. Many hostsworth allowing are multi-tenant with the tenant in the path, so the narrowest
policy the allowlist can express is "every tenant on that host":
storage.googleapis.comghcr.io<region>-docker.pkg.devraw.githubusercontent.comHost-scoped alternatives exist for some of these (
<bucket>.s3.amazonaws.com,<account>.blob.core.windows.net) and the allowlist handles those fine. The gapis the path-style form, which clients don't always let you choose.
Desired state
An allowed domain can optionally be narrowed to path prefixes, expressed as a
side map keyed off an
allowedDomainsentry — the waydeniedDomainReasonsiskeyed off
deniedDomains:{ "network": { "allowedDomains": ["storage.googleapis.com", "raw.githubusercontent.com"], "allowedDomainPaths": { "storage.googleapis.com": ["/my-bucket/"], "raw.githubusercontent.com": ["/my-org/"] } } }A host absent from the map behaves exactly as it does today. A host present is
reachable only for requests under one of its prefixes.
Context
Found while hardening a sandbox configuration with a deliberately small
allowlist, where a shared object-store host had to be allowed in full to unblock
one bucket's worth of legitimate traffic.