mirror of
https://github.com/transloadit/uppy.git
synced 2026-07-17 16:50:22 +00:00
Part of the dev-dependency major-version upgrades. These required code changes so they're split out from the no-code-change batch (#6315). **AI Disclaimer** : AI Used - **glob 8 → 13** — `@uppy/locales` scripts: the callback API was removed, so `getPaths()` uses the promise form and `test.mjs` uses the named `globSync`. - **npm-packlist 5 → 11** — `upload-to-cdn.js`: v7+ takes an `@npmcli/arborist` tree instead of `{ path }`; loads the tree and passes it to `packlist()`. Adds `@npmcli/arborist` as a devDependency. - **nock 13 → 14** (`@uppy/companion`) — the v14 @mswjs/interceptors rewrite crashed the SSRF tests in `http-agent.test.ts`; nock interception is now kept off by default and only activated for the one test that mocks a host. - **@types/use-sync-external-store 0 → 1** — `@uppy/react`: v1's exports map only exposes extensionless subpaths, so imports use `use-sync-external-store/shim` and `/with-selector` (runtime supports both).
89 lines
2.9 KiB
TypeScript
89 lines
2.9 KiB
TypeScript
import nock from 'nock'
|
|
import { afterEach, beforeEach, describe, expect, test } from 'vitest'
|
|
import {
|
|
FORBIDDEN_IP_ADDRESS,
|
|
getProtectedGot,
|
|
} from '../src/server/helpers/request.js'
|
|
|
|
// nock 14 activates HTTP interception (via @mswjs/interceptors) on import. The
|
|
// "blocks ..." tests below rely on the protected agent rejecting the connection
|
|
// itself — no response is mocked — and the agent rejects forbidden literal IPs
|
|
// synchronously in createConnection with a non-connected socket, which trips
|
|
// nock's passthrough ("Cannot use 'in' operator ... '_handle' in undefined").
|
|
// So keep interception OFF by default and only enable it for the one test that
|
|
// actually mocks a host. nock 14 is active on import, so restore both before
|
|
// each test (so the first test can re-activate cleanly) and after each test
|
|
// (so interception is never left enabled for subsequent test files).
|
|
beforeEach(() => {
|
|
if (nock.isActive()) nock.restore()
|
|
})
|
|
afterEach(() => {
|
|
nock.cleanAll()
|
|
if (nock.isActive()) nock.restore()
|
|
})
|
|
|
|
describe('test protected request Agent', () => {
|
|
test('allows URLs without IP addresses', async () => {
|
|
nock.activate()
|
|
nock('https://transloadit.com').get('/').reply(200)
|
|
const url = 'https://transloadit.com'
|
|
return getProtectedGot({ allowLocalIPs: false }).get(url)
|
|
})
|
|
|
|
test('blocks url that resolves to forbidden IP', async () => {
|
|
const url = 'https://localhost'
|
|
await expect(
|
|
getProtectedGot({ allowLocalIPs: false }).get(url),
|
|
).rejects.toThrow(/^Forbidden resolved IP address/)
|
|
})
|
|
|
|
test('blocks private http IP address', async () => {
|
|
const url = 'http://172.20.10.4:8090'
|
|
await expect(
|
|
getProtectedGot({ allowLocalIPs: false }).get(url),
|
|
).rejects.toThrow(FORBIDDEN_IP_ADDRESS)
|
|
})
|
|
|
|
test('blocks private https IP address', async () => {
|
|
const url = 'https://172.20.10.4:8090'
|
|
await expect(
|
|
getProtectedGot({ allowLocalIPs: false }).get(url),
|
|
).rejects.toThrow(FORBIDDEN_IP_ADDRESS)
|
|
})
|
|
|
|
test('blocks various private IP addresses', async () => {
|
|
// taken from: https://github.com/transloadit/uppy/blob/4aeef4dac0490ebb1d1fccd5582ba42c6c0fb87d/packages/%40uppy/companion/src/server/helpers/request.js#L14
|
|
const ipv4s = [
|
|
'0.0.0.0',
|
|
'0.0.0.1',
|
|
'127.0.0.1',
|
|
'127.16.0.1',
|
|
'192.168.1.1',
|
|
'169.254.1.1',
|
|
'10.0.0.1',
|
|
]
|
|
|
|
const ipv6s = [
|
|
'fd80::1234:5678:abcd:0123',
|
|
'fe80::1234:5678:abcd:0123',
|
|
'ff00::1234',
|
|
'::ffff:192.168.1.10',
|
|
'::1',
|
|
'0:0:0:0:0:0:0:1',
|
|
'fda1:3f9f:dbf7::1c8d',
|
|
]
|
|
|
|
for (const ip of ipv4s) {
|
|
const url = `http://${ip}:8090`
|
|
await expect(
|
|
getProtectedGot({ allowLocalIPs: false }).get(url),
|
|
).rejects.toThrow(FORBIDDEN_IP_ADDRESS)
|
|
}
|
|
for (const ip of ipv6s) {
|
|
const url = `http://[${ip}]:8090`
|
|
await expect(
|
|
getProtectedGot({ allowLocalIPs: false }).get(url),
|
|
).rejects.toThrow(FORBIDDEN_IP_ADDRESS)
|
|
}
|
|
})
|
|
})
|