Download server/netGuard.ts from igorktech/pinned: direct link, hf CLI and curl.
- Browser
- Download file 1.99 kB
-
https://huggingface.co/spaces/igorktech/pinned/resolve/main/server/netGuard.ts
- Command line
-
hf download hf://spaces/igorktech/pinned/server/netGuard.ts
-
curl -L -o netGuard.ts https://huggingface.co/spaces/igorktech/pinned/resolve/main/server/netGuard.ts
1.99 kB
| import { lookup } from 'node:dns/promises' | |
| import { BlockList, isIP } from 'node:net' | |
| // URLs that come from users (pasted bookmarks, paper links) must never make the server | |
| // request itself, the cloud metadata service or anything else on a private network. | |
| // BlockList also checks IPv4-mapped IPv6 addresses (::ffff:127.0.0.1) against the IPv4 rules. | |
| const blocked = new BlockList() | |
| for (const [net, prefix] of [ | |
| ['0.0.0.0', 8], | |
| ['10.0.0.0', 8], | |
| ['100.64.0.0', 10], | |
| ['127.0.0.0', 8], | |
| ['169.254.0.0', 16], | |
| ['172.16.0.0', 12], | |
| ['192.0.0.0', 24], | |
| ['192.168.0.0', 16], | |
| ['198.18.0.0', 15], | |
| ['224.0.0.0', 4], | |
| ['240.0.0.0', 4], | |
| ] as const) { | |
| blocked.addSubnet(net, prefix, 'ipv4') | |
| } | |
| for (const [net, prefix] of [ | |
| ['::', 128], | |
| ['::1', 128], | |
| ['fc00::', 7], | |
| ['fe80::', 10], | |
| ['ff00::', 8], | |
| ] as const) { | |
| blocked.addSubnet(net, prefix, 'ipv6') | |
| } | |
| export async function assertPublicUrl(url: URL) { | |
| if (url.protocol !== 'http:' && url.protocol !== 'https:') { | |
| throw new Error(`Blocked protocol ${url.protocol}`) | |
| } | |
| const host = url.hostname.replace(/^\[|\]$/g, '') | |
| const addresses = isIP(host) ? [{ address: host }] : await lookup(host, { all: true }) | |
| for (const { address } of addresses) { | |
| if (blocked.check(address, isIP(address) === 6 ? 'ipv6' : 'ipv4')) { | |
| throw new Error(`Blocked private address ${address} for ${url.hostname}`) | |
| } | |
| } | |
| } | |
| // fetch that checks the address of every hop in a redirect chain, not just the first URL | |
| export async function publicFetch(input: string, init: RequestInit = {}, maxRedirects = 3) { | |
| let url = new URL(input) | |
| for (let hop = 0; ; hop++) { | |
| await assertPublicUrl(url) | |
| const res = await fetch(url, { | |
| ...init, | |
| redirect: 'manual', | |
| signal: init.signal ?? AbortSignal.timeout(5000), | |
| }) | |
| const location = res.headers.get('location') | |
| if (res.status < 300 || res.status >= 400 || !location) return res | |
| if (hop >= maxRedirects) throw new Error(`More than ${maxRedirects} redirects`) | |
| url = new URL(location, url) | |
| } | |
| } | |