npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tak-ps/node-safeurl

v1.4.0

Published

SSRF-safe URL validation library for Node.js

Readme

Lightweight TypeScript library for validating URLs to prevent Server-Side Request Forgery (SSRF) attacks. It blocks requests to private IP ranges, localhost, link-local addresses, and other special-purpose networks using Microsoft's maintained @microsoft/antissrf block lists.

About

node-safeurl provides the following exports:

  • fetch(input, init?) — SSRF-safe drop-in replacement for the global fetch. Validates the URL (and every redirect hop) before making the request, and returns a TypedResponse. Pass { safeUrl: false } to opt out of validation entirely, or { safeUrlAllow: [...] } to allow specific private-network origins while keeping all other SSRF checks active.
  • TypedResponse — Subclass of Response that adds a .typed(schema) method for runtime-validated JSON parsing via TypeBox.
  • FetchInit — TypeScript interface extending RequestInit with the optional safeUrl boolean and safeUrlAllow string-array fields.
  • isSafeUrl(href, opts?) — Async function that validates a URL is safe to fetch. Checks protocol, hostname, IP literals, and performs DNS resolution to guard against DNS rebinding attacks. Pass { allow: [...] } to exempt specific origins or hostnames from all checks.
  • SafeUrlOptions — TypeScript interface for the options accepted by isSafeUrl.
  • isPrivateIPv4(address) — Synchronous check for private/special-purpose IPv4 addresses.
  • isPrivateIPv6(address) — Synchronous check for private/special-purpose IPv6 addresses.

Installation

NPM

npm install @tak-ps/node-safeurl

Usage

import fetch, { isSafeUrl, isPrivateIPv4, isPrivateIPv6 } from '@tak-ps/node-safeurl';
import { Type } from '@sinclair/typebox';

// SSRF-safe fetch — validates the URL and every redirect hop automatically
const res = await fetch('https://example.com/api/data');
const data = await res.typed(Type.Object({ id: Type.Number() }));

// Opt out of SSRF validation entirely for trusted internal calls
const internal = await fetch('http://localhost:3000/health', { safeUrl: false });

// Allow a specific private-network origin while keeping all other SSRF checks active
const api = await fetch('http://10.0.0.5:8080/api/status', {
    safeUrlAllow: ['http://10.0.0.5:8080'],
});

// Validate a URL manually before fetching
const result = await isSafeUrl('https://example.com/api');
if (result.safe) {
    // Safe to fetch
    const response = await fetch(result.url);
} else {
    console.error('Blocked:', result.reason);
}

// Validate a URL while allowing a known private endpoint
const result2 = await isSafeUrl('http://192.168.1.10/health', {
    allow: ['192.168.1.10'],
});

// Check individual IPs
isPrivateIPv4('192.168.1.1');  // true
isPrivateIPv4('8.8.8.8');      // false
isPrivateIPv6('::1');          // true
isPrivateIPv6('2606:4700:4700::1111'); // false

API

fetch(input, init?): Promise<TypedResponse>

SSRF-safe drop-in replacement for the global fetch. Validates the initial URL and every redirect destination against isSafeUrl before the request is made. Throws an Err(403) if a URL is deemed unsafe.

init accepts all standard RequestInit options plus:

  • safeUrl (boolean, default true) — set to false to skip all SSRF validation (e.g. for fully trusted internal endpoints).
  • safeUrlAllow (string[], default []) — list of origins (e.g. "http://10.0.0.5:8080") or bare hostnames (e.g. "10.0.0.5") that bypass SSRF checks while all other URLs remain validated. Use this instead of safeUrl: false when only specific private-network endpoints need to be exempted.

Custom dispatcher options are rejected when safeUrl is true because they can bypass SSRF protection.

TypedResponse

Subclass of Response returned by fetch. Adds:

.typed<T>(schema: TSchema): Promise<Static<T>>

Parses the response body as JSON and validates it against a TypeBox schema. Throws Err(500) if validation fails.

const res = await fetch('https://api.example.com/user/1');
const user = await res.typed(Type.Object({
    id: Type.Number(),
    name: Type.String(),
}));

FetchInit

TypeScript interface extending RequestInit with additional fields:

interface FetchInit extends RequestInit {
    safeUrl?: boolean;      // default: true — set false to skip all SSRF checks
    safeUrlAllow?: string[]; // origins or hostnames exempt from SSRF checks
}

isSafeUrl(href: string, opts?: SafeUrlOptions): Promise<{ safe: boolean; url?: URL; reason?: string }>

Validates that a URL is safe to fetch from a server context. Returns an object with:

  • safetrue if the URL is safe, false if it should be blocked
  • url — The parsed URL object (when the URL could be parsed)
  • reason — A human-readable string explaining why the URL was blocked

opts accepts:

  • allow (string[]) — origins (e.g. "http://10.0.0.5:8080") or bare hostnames that are unconditionally considered safe, bypassing all checks below.

Checks performed (when not matched by allow):

  1. URL must be parseable
  2. Protocol must be http: or https:
  3. Hostname must not be localhost or 0.0.0.0
  4. IP literal hostnames must not be in private/special-purpose ranges
  5. DNS resolution results must not map to private/special-purpose IPs

SafeUrlOptions

interface SafeUrlOptions {
    allow?: string[]; // origins or hostnames exempt from all SSRF checks
}

isPrivateIPv4(hostname: string): boolean

Returns true if the given string is a valid IPv4 address in a private or special-purpose range.

isPrivateIPv6(address: string): boolean

Returns true if the given string is a valid IPv6 address in a private or special-purpose range.

Blocked Ranges

The following ranges are blocked (via @microsoft/antissrf):

  • IPv4: Loopback (127.0.0.0/8), RFC 1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), Link-local (169.254.0.0/16), CGNAT (100.64.0.0/10), and more
  • IPv6: Loopback (::1/128), ULA (fc00::/7), Link-local (fe80::/10), IPv4-mapped (::ffff:0:0/96), and more

License

MIT