fix: fail closed on non-HTTP(S) and link-local CCIP Read URLs - #5024
fix: fail closed on non-HTTP(S) and link-local CCIP Read URLs#5024SashaMIT wants to merge 2 commits into
Conversation
A resolver-supplied gateway URL could use file: or a link-local metadata address, and fetch followed redirects. Reject those hosts and schemes before the request, and do not follow redirects.
|
@SashaMIT is attempting to deploy a commit to the Wevm Team on Vercel. A member of the Team first needs to authorize it. |
🦋 Changeset detectedLatest commit: 95e5b76 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
official-burak
left a comment
There was a problem hiding this comment.
IPv6 literals never hit the new block list. Node keeps brackets on URL.hostname, and v4-mapped link-local addresses are a second miss.
| } | ||
| } | ||
|
|
||
| function isBlockedCcipHostname(hostname: string) { |
There was a problem hiding this comment.
Node's URL.hostname keeps brackets on IPv6 literals:
new URL('http://[::]/').hostnameis'[::]'new URL('http://[fe80::1]/').hostnameis'[fe80::1]'new URL('http://[::ffff:169.254.169.254]/').hostnameis'[::ffff:a9fe:a9fe]'
None of those equal '::', start with 'fe80:', or match the dotted-quad regex, so the v6 and IPv4-mapped link-local cases this PR is meant to reject still go through to fetch.
Strip brackets before the checks. Run :ffff: mapped addresses through the same 169.254 / 0.0.0.0/8 rules.
Node keeps brackets on URL.hostname and rewrites ::ffff:a.b.c.d to hex, so the first pass missed those literals.
|
Good catch. Node keeps the brackets and rewrites the mapped form to hex, so those never hit the first checks. The guard now strips brackets and runs v4-mapped addresses through the same 169.254 / 0.0.0.0/8 rules. Added tests for |
|
Looks right. Stripping brackets and running v4-mapped addresses through the same 169.254 / 0.0.0.0/8 checks covers the two misses. |
ccipRequestfetched resolver-supplied gateway URLs with no scheme or host check, andfetchfollowed redirects.A contract
OffchainLookupcan returnfile:///...orhttp://169.254.169.254/.... On Node that becomes a client-side request to a local file or link-local metadata address. A public URL that 302s to the same place had the same effect.This is the URL-validation class web3.py already applies in
validate_ccip_url_scheme/validate_ccip_url_host. Loopback HTTP stays allowed so local gateways and the existing test servers keep working. Callers who want a stricter allowlist can still wrapccipRead.request.Change
http(s)schemes beforefetch.0.0.0.0/8and169.254.0.0/16, plus IPv6 unspecified andfe80:link-local literals.redirect: 'manual'so a public gateway cannot bounce the client onto a blocked host.Test
SKIP_GLOBAL_SETUP=true pnpm exec vitest run -c ./test/vitest.config.ts --project core src/utils/ccipRequest.url.test.ts(4/4). Revert-tested: the three reject assertions fail when the pre-fetch guards are removed.