nodejs/undici

SSRF protection in undici / native-node-fetch

Open

#2 019 ouverte le 21 mars 2023

Voir sur GitHub
 (14 commentaires) (3 réactions) (0 assignés)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!

Guide contributeur