nodejs/undici

SSRF protection in undici / native-node-fetch

Open

#2019 opened on Mar 21, 2023

View on GitHub
 (14 comments) (3 reactions) (0 assignees)JavaScript (5,319 stars) (444 forks)batch import
enhancementgood first issue

Description

This would solve...

undici and native-node>=18-fetch expose (as far as I know, and see documented) no way to protect against SSRF attacks when making server-side calls to arbitrary / user-controllable URLs (that are normally WWW, but could be abused to try to exfiltrate info from an internal network).

In the nodejs ecosystem,

  • Non-fetch libs like request or axios can use middleware like ssrf-req-filter. It provides an agent / httpAgent / httpsAgent that you can pass in these libs second options argument:
const ssrfFilter = require('ssrf-req-filter');
const url = 'http://169.254.169.254/latest/user-data/iam/security-credentials/' // your choice of sensitive "internal" URL here
axios.get(url, { httpAgent: ssrfFilter(url), httpsAgent: ssrfFilter(url) }) // <-- SSRF "PLUGIN" ADDED HERE
    .then((response) => { console.log(`Success', response) });
    .catch((error) => { console.log('Error', error); })
  • 3rd-party fetch lib node-fetch also supports ssrf-req-filter, though a similar agent API:
const ssrfFilter = require('ssrf-req-filter');
const nodefetch = require("node-fetch");
const url = 'http://169.254.169.254/latest/user-data/iam/security-credentials/' // your choice of sensitive "internal" URL here
nodefetch(url, { agent: ssrfFilter(url) }) // <-- SSRF "PLUGIN" ADDED HERE
    .then((response) => { console.log(`Success', response) });
    .catch((error) => { console.log('Error', error); })

The implementation of such SSRF protection is out of topic, but:

Given the above, my question:

In undici / built-in-node>=18 native fetch, I see no trace of supporting such agents with a ({host: string}) => boolean signature letting me decide at runtime to cancel a request.

  • Is it actually unsupported, with no plan to support it? If so, what do you (undici/native-node-fetch maintainers) recommend to do to protect against SSRF? To make the SSRF check before calling fetch? (At the cost of an extra DNS resolution before calling fetch)
  • Is it unsupported in browser fetch, but potentially coming to server-side node fetch at some point?
  • Or is it supported but lacks documentation (or I missed it 😄?)

The implementation should look like...

undici (fetch?) should support setting kind of option letting users plug anti-SSRF logic.

Typically, an agent function of signature {host: string} => boolean (agent is passed an IP, and expected to return a boolean).

I have also considered...

I searched undici's open & closed issues for ssrf, nothing. Grepping for agent yields many things but it looks like there's a naming collision around what is an agent in your context vs. in an axios/request context. They don't seem to have similar responsibilities.

I searched undici's discussions for ssrf, nothing.

I read the options supported by standard fetch in mdn / fetch, nothing in the documented options I could find related to agent / ssrf stuff.

I grepped the fetch WHATWG spec for "SSRF", without success.

Additional context

Related to CVE-2023-28155 / request #3442

Thanks for fetch!

Contributor guide