You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(egress): fold NAT64 addresses, and parse the boundary check properly
A DNS64 resolver returns an IPv4 destination wrapped in the RFC 6052 well-known
prefix, so `64:ff9b::a9fe:a9fe` is the metadata endpoint. Canonicalization did
not recognise that, and an allowlisted hostname resolving there was permitted —
probed and confirmed. Narrower than it first looked: `isPrivateIp` already
rejects every NAT64 form, so an ordinary destination was never exposed; the hole
was only for a vouched one, where the class check is skipped and the metadata
exception is all that stands in the way. Folding it also makes an operator's
IPv4 range match the NAT64 spelling of an address inside it.
The boundary check is parsed with the TypeScript AST instead of matched with a
regex. Two rounds found holes in both directions — a comment or string naming a
transport reported a violation that did not exist, and a regex literal
containing a quote hid one that did — which is what a scanner that does not
understand the grammar will keep doing. A template interpolation was the third.
Parsing surfaced a false positive the regex never had: `import { type X } from
'undici'` is elided under `verbatimModuleSyntax: false`, so it cannot load
anything. Elision is now modelled properly — a default or namespace binding
keeps an import alive, an all-type named import does not. Eleven forms verified
by probe.
That needs `@typescript/typescript6` declared at the root rather than relied on
by hoisting from apps/sim. It adds no new `tsc` bin, and check:native-typecheck
still reports 7.0.2.
Docs: the provenance table was missing `proxy`, and the line about naming a
destination read as though the allowlist reaches everything. It does not reach a
content fetch or a proxy — a proxy must be public, since it decides where every
other request may go.
Content fetches never reach a private destination, allowlist or not — that is the class where SSRF is actually exploited.
148
+
Content fetches never reach a private destination, allowlist or not — that is the class where SSRF is actually exploited. Nor does the proxy: it is the component deciding where everything else may go, so it is held to public destinations regardless of what the allowlist says.
148
149
149
150
Deployments frequently need to reach an internal service by name or address. Name the destinations:
150
151
@@ -157,6 +158,8 @@ A wildcard (`*.svc.cluster.local`) and a broad range (`10.0.0.0/8`) are accepted
157
158
158
159
Naming a destination permits plain HTTP to it and lifts the blocked-port list for it, since those are the same decision about the same host. Cloud metadata endpoints (`169.254.169.254` and equivalents) stay blocked no matter how broad the allowlist is, and both variables are ignored entirely on Sim Cloud.
159
160
161
+
The allowlist reaches the four provenances marked **Yes** above. It does not reach a content fetch, and it does not reach a proxy: an HTTP block's `proxyUrl` must be a public address, because the proxy is what decides where every other request may go. Adding an internal proxy to the allowlist will not make it work.
162
+
160
163
To reach a service on the Docker host, pair the allowlist with the host alias that Compose already sets up:
0 commit comments