Skip to content

fix(inspect): validate metadata URI before fetching (SSRF)#12

Open
Nexory wants to merge 1 commit into
ProjectOpenSea:mainfrom
Nexory:fix/inspect-metadata-uri-ssrf
Open

fix(inspect): validate metadata URI before fetching (SSRF)#12
Nexory wants to merge 1 commit into
ProjectOpenSea:mainfrom
Nexory:fix/inspect-metadata-uri-ssrf

Conversation

@Nexory

@Nexory Nexory commented Jun 13, 2026

Copy link
Copy Markdown

What

inspect fetches the on-chain metadataURI with no validation. This validates it first so a hostile registry entry cannot point the fetch at an internal address.

Why

metadataURI is read from the tool registry, which any party can write to permissionlessly, and inspect passes it straight to fetch (src/cli/commands/inspect.ts). A registrant can store http://169.254.169.254/latest/meta-data/... and post the tool id; a developer or CI runner that runs tool-sdk inspect --tool-id <id> then issues that request to the cloud metadata endpoint from inside the trust boundary. The isPrivateHostname guard already exists (it is applied to manifest.endpoint) but was never applied to metadataURI, and its PRIVATE_HOSTNAME_RE did not cover the link-local range the metadata endpoint lives in.

Change

  • Validate metadataURI before fetching: reject a private/internal host (reusing isPrivateHostname) and reject non-http(s) schemes.
  • Add the link-local range 169.254.0.0/16 (which contains 169.254.169.254) to PRIVATE_HOSTNAME_RE, so the endpoint probe flags it too.

Tests

Adds a regression test that a link-local metadataURI is never fetched. Against the current code it fails (the address is fetched):

AssertionError: expected "spy" to not be called at all, but actually been called 1 times

With the fix it passes and the full suite stays green:

Test Files  39 passed (39)
      Tests  633 passed (633)

`inspect` reads `metadataURI` from the on-chain registry, which any
registrant can write, and fetched it with no checks. A hostile entry
could point the fetch at an internal address (e.g. cloud metadata at
169.254.169.254) from the machine or CI runner that runs `inspect`.

- Reject a metadata URI whose host is a private/internal address before
  fetching, reusing `isPrivateHostname`.
- Reject non-http(s) schemes.
- Add the link-local range (169.254.0.0/16, which covers the cloud
  metadata endpoint) to `PRIVATE_HOSTNAME_RE`; it was previously absent,
  so the endpoint probe did not flag it either.

Adds a regression test that a link-local metadata URI is never fetched.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant