nodejs / nodejs/undici

SSRF protection in undici / native-node-fetch

Open
#2,019 19 comments 4 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement good first issue
Dominant language
JavaScript
Stars
7.7k
Forks
880
Avg merge
2d 16h
Merged PRs (30d)
68

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with undici's fetch and agent option handling, then compare the referenced ssrf-req-filter lib/index.js and ipaddr.js behavior. Define the runtime decision API and its server-side scope before implementation; done should include documented protection behavior and coverage for requests to internal addresses.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
backend-api-design, networking, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.