Skip to content

An http(s).Agent implementation that block request Private/Reserved IP addresses. Prevent SSRF.

License

Notifications You must be signed in to change notification settings

azu/request-filtering-agent

Repository files navigation

request-filtering-agent Actions Status

An http(s).Agent class block the request to Private IP addresses and Reserved IP addresses.

It helps to prevent server-side request forgery (SSRF) attack.

This library depends on ipaddr.js definitions. This library blocks the request to these IP addresses by default.

So, This library block the request to non-unicast IP addresses.

⚠️ Node.js's built-in fetch does not support http.Agent.

Support http.Agent libraries

This library provides Node.js's http.Agent implementation. http.Agent is supported by popular library.

request-filtering-agent works with these libraries!

Install

Install with npm:

npm install request-filtering-agent

Support Node.js version

Version Node.js 12 Node.js 14 Node.js 16 Node.js 18 Node.js 20
v1.x.x Support Support Support Support Not Support
v2.0.0 No Support No Support No Support Support Support

Usage

useAgent(url, options) return an agent for the url.

The agent blocks the request to Private network and Reserved IP addresses by default.

const fetch = require("node-fetch");
const { useAgent } = require("request-filtering-agent");
const url = 'http://127.0.0.1:8080/';
fetch(url, {
    // use http or https agent for url
    agent: useAgent(url)
}).catch(err => {
    console.err(err); // DNS lookup 127.0.0.1(family:4, host:127.0.0.1.nip.io) is not allowed. Because, It is private IP address.
});

request-filtering-agent support loopback domain like nip.io. This library detects the IP address that is dns lookup-ed.

$ dig 127.0.0.1.nip.io

;127.0.0.1.nip.io.		IN	A

;; ANSWER SECTION:
127.0.0.1.nip.io.	300	IN	A	127.0.0.1

Example code:

const fetch = require("node-fetch");
const { useAgent } = require("request-filtering-agent");
const url = 'http://127.0.0.1.nip.io:8080/';
fetch(url, {
    agent: useAgent(url) // use http or https agent for url
}).catch(err => {
    console.err(err); // DNS lookup 127.0.0.1(family:4, host:127.0.0.1.nip.io) is not allowed. Because, It is private IP address.
});

It will prevent DNS rebinding

API

export interface RequestFilteringAgentOptions {
    // Allow to connect private IP address
    // This includes Private IP addresses and Reserved IP addresses.
    // https://en.wikipedia.org/wiki/Private_network
    // https://en.wikipedia.org/wiki/Reserved_IP_addresses
    // Example, http://127.0.0.1/, http://localhost/, https://169.254.169.254/
    // Default: false
    allowPrivateIPAddress?: boolean;
    // Allow to connect meta address 0.0.0.0
    // 0.0.0.0 (IPv4) and :: (IPv6) a meta address that routing another address
    // https://en.wikipedia.org/wiki/Reserved_IP_addresses
    // https://tools.ietf.org/html/rfc6890
    // Default: false
    allowMetaIPAddress?: boolean;
    // Allow address list
    // This values are preferred than denyAddressList
    // Default: []
    allowIPAddressList?: string[];
    // Deny address list
    // Default: []
    denyIPAddressList?: string[];
}
/**
 * A subclass of http.Agent with request filtering
 */
export declare class RequestFilteringHttpAgent extends http.Agent {
    constructor(options?: http.AgentOptions & RequestFilteringAgentOptions);
}
/**
 * A subclass of https.Agent with request filtering
 */
export declare class RequestFilteringHttpsAgent extends https.Agent {
    constructor(options?: https.AgentOptions & RequestFilteringAgentOptions);
}
export declare const globalHttpAgent: RequestFilteringHttpAgent;
export declare const globalHttpsAgent: RequestFilteringHttpsAgent;
/**
 * Get an agent for the url
 * return http or https agent
 * @param url
 */
export declare const useAgent: (url: string, options?: https.AgentOptions & RequestFilteringAgentOptions) => RequestFilteringHttpAgent | RequestFilteringHttpsAgent;

Example: Create an Agent with options

An agent that allow requesting 127.0.0.1, but it disallows other Private IP.

const fetch = require("node-fetch");
const { RequestFilteringHttpAgent } = require("request-filtering-agent");

// Create http agent that allow 127.0.0.1, but it disallow other private ip
const agent = new RequestFilteringHttpAgent({
    allowIPAddressList: ["127.0.0.1"], // it is preferred than allowPrivateIPAddress option
    allowPrivateIPAddress: false, // Default: false
});
// 127.0.0.1 is private ip address, but it is allowed
const url = 'http://127.0.0.1:8080/';
fetch(url, {
    agent: agent
}).then(res => {
    console.log(res); // OK
});

Related

Changelog

See Releases page.

Running tests

Install devDependencies and Run yarn test:

yarn test

📝 This testing require IPv6 supports:

  • Travis CI: NG
  • GitHub Actions: OK

Contributing

Pull requests and stars are always welcome.

For bugs and feature requests, please create an issue.

For security issue, please see SECURITY.md

  1. Fork it!
  2. Create your feature branch: git checkout -b my-new-feature
  3. Commit your changes: git commit -am 'Add some feature'
  4. Push to the branch: git push origin my-new-feature
  5. Submit a pull request :D

Author

License

MIT © azu

About

An http(s).Agent implementation that block request Private/Reserved IP addresses. Prevent SSRF.

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Sponsor this project

 

Contributors 4

  •  
  •  
  •  
  •