{"_id":"@advance-labs/net-guard","_rev":"3-db76bae5af44b0fa89e4e1cc938fe80a","name":"@advance-labs/net-guard","dist-tags":{"latest":"0.2.2"},"versions":{"0.2.0":{"name":"@advance-labs/net-guard","version":"0.2.0","license":"MIT","_id":"@advance-labs/net-guard@0.2.0","maintainers":[{"name":"zordhalo","email":"lucas@advancelabs.dev"}],"homepage":"https://github.com/Advance-Labs/aeo-toolkit#readme","bugs":{"url":"https://github.com/Advance-Labs/aeo-toolkit/issues"},"dist":{"shasum":"2b24c8a902bb747fe8000e55c94b3c56f08aba01","tarball":"https://registry.npmjs.org/@advance-labs/net-guard/-/net-guard-0.2.0.tgz","fileCount":6,"integrity":"sha512-aN4taBCgIEPNdoZ5iA+IFqJ/p/cIitLdRzlvA1mFXJaRcIQPQcb3p1I7vONLp9FSL6hpa7oFm8PaFLTF5t/wYA==","signatures":[{"sig":"MEUCIQDCxFJLGXeTWxfTiFzWJY8X2XAtwdTepCsUZWk9EoINJQIgGVjUjrXh1PASDdldG+BlVEKcBDrgrADoUSZT2BV9nLA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":28553},"main":"./dist/index.js","type":"module","_from":"file:advance-labs-net-guard-0.2.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"tsup --watch","lint":"eslint src","test":"vitest run","build":"tsup","clean":"rimraf dist .turbo","typecheck":"tsc --noEmit"},"_npmUser":{"name":"zordhalo","email":"lucas@advancelabs.dev"},"_resolved":"/private/var/folders/lc/qg6736_d3pxb5ds7q4x5gtf80000gn/T/9d675e3d4dc206340d6f871e407951cc/advance-labs-net-guard-0.2.0.tgz","_integrity":"sha512-aN4taBCgIEPNdoZ5iA+IFqJ/p/cIitLdRzlvA1mFXJaRcIQPQcb3p1I7vONLp9FSL6hpa7oFm8PaFLTF5t/wYA==","repository":{"url":"git+https://github.com/Advance-Labs/aeo-toolkit.git","type":"git","directory":"packages/net-guard"},"_npmVersion":"11.18.0","description":"SSRF-guarded HTTP fetch seam — DNS-resolves and rejects private/loopback/link-local/CGNAT/cloud-metadata addresses, re-validates every redirect hop, caps body size and time, and host-pins to defeat DNS rebinding.","directories":{},"_nodeVersion":"25.8.1","dependencies":{"@advance-labs/types":"0.2.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","rimraf":"^6.0.1","vitest":"^3.2.6","typescript":"^5.7.2","@types/node":"^22.10.2","@advance-labs/config":"0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/net-guard_0.2.0_1788059627589_0.8997484659188986","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@advance-labs/net-guard","version":"0.2.1","keywords":["ssrf","security","fetch","http","dns-rebinding","url-validation","allowlist"],"license":"Apache-2.0","_id":"@advance-labs/net-guard@0.2.1","maintainers":[{"name":"zordhalo","email":"lucas@advancelabs.dev"}],"homepage":"https://github.com/Advance-Labs/aeo-toolkit#readme","bugs":{"url":"https://github.com/Advance-Labs/aeo-toolkit/issues"},"dist":{"shasum":"edda1d1f48e3cb06b7097a3ae7dde5c84edeb0b7","tarball":"https://registry.npmjs.org/@advance-labs/net-guard/-/net-guard-0.2.1.tgz","fileCount":6,"integrity":"sha512-fb3OXJ2rxHwivDVvxhfptMZ2f4BhNhk6fqg/gZE3kUhpN/wvBRwPBqyfE81612kvzEjZ2wDcuGijV09JVnkoNQ==","signatures":[{"sig":"MEUCIQDh44y2soyd1DoJhuSetLw4GBzfb0RdEMFTegODcqflAwIgW+mUBQiijGuJXQ3FPxOaHeO3062mjXzbhEdJ4W4mzrw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIFKo4a9KhFexByRSO0Y0B2BA1/nZavtHJEjLuC8SU6w5AiEA1whl8TmBPR5A3pblleI8pzK7UO2AnizKywXmvOOtUto=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":38994},"main":"./dist/index.js","type":"module","_from":"file:advance-labs-net-guard-0.2.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"tsup --watch","lint":"eslint src","test":"vitest run","build":"tsup","clean":"rimraf dist .turbo","typecheck":"tsc --noEmit"},"_npmUser":{"name":"zordhalo","email":"lucas@advancelabs.dev"},"_resolved":"/tmp/c98fe3d74c6e0305674f86399ad27c70/advance-labs-net-guard-0.2.1.tgz","_integrity":"sha512-fb3OXJ2rxHwivDVvxhfptMZ2f4BhNhk6fqg/gZE3kUhpN/wvBRwPBqyfE81612kvzEjZ2wDcuGijV09JVnkoNQ==","repository":{"url":"git+https://github.com/Advance-Labs/aeo-toolkit.git","type":"git","directory":"packages/net-guard"},"_npmVersion":"11.19.0","description":"SSRF-guarded HTTP fetch seam — DNS-resolves and rejects private/loopback/link-local/CGNAT/cloud-metadata addresses, re-validates every redirect hop, caps body size and time, and host-pins to defeat DNS rebinding.","directories":{},"_nodeVersion":"24.20.0","dependencies":{"@advance-labs/types":"0.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","rimraf":"^6.0.1","vitest":"^3.2.6","typescript":"^5.7.2","@types/node":"^22.10.2","@advance-labs/config":"0.1.0"},"_npmOperationalInternal":{"tmp":"tmp/net-guard_0.2.1_1789019552846_0.5287512123810225","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"_id":"@advance-labs/net-guard@0.2.2","bugs":{"url":"https://github.com/Advance-Labs/aeo-toolkit/issues"},"dist":{"shasum":"3644aeca691bfaced9feee7e2634ef013b030d9f","tarball":"https://registry.npmjs.org/@advance-labs/net-guard/-/net-guard-0.2.2.tgz","fileCount":6,"integrity":"sha512-Iy0orK8wvoZvsLh75ThR0stRojO87VFPJuIsCPaBEuGJw+37bjZlsKpyTmP/L3HlssuDMD/NPPFy+Y5XoooTLA==","signatures":[{"sig":"MEYCIQDtNa4+6YYJIu8gv+SvARoB0W4p4pG6K+H70aQkA8v6QAIhAO3tPoOBqm4I4iqjX2XKe1SAqEBeyBydof2FV9BLNLJ9","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDBsPoKd6ioCz9r9eiImcPQ0aqjMGXDway5LjzU4Y3m3QIgSwfqhMWTt8AFWacwZJbWrO7TZoZb+SnVyUKyMo8T2HA="}],"unpackedSize":39070},"main":"./dist/index.js","name":"@advance-labs/net-guard","type":"module","_from":"file:advance-labs-net-guard-0.2.2.tgz","types":"./dist/index.d.ts","author":{"url":"https://advancelabs.dev/lucas","name":"Lucas Krawczak","email":"lucas@advancelabs.dev"},"module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"license":"Apache-2.0","scripts":{"dev":"tsup --watch","lint":"eslint src","test":"vitest run","build":"tsup","clean":"rimraf dist .turbo","typecheck":"tsc --noEmit"},"version":"0.2.2","_npmUser":{"name":"zordhalo","email":"lucas@advancelabs.dev"},"homepage":"https://docs.advancelabs.dev/aeo-toolkit","keywords":["ssrf","security","fetch","http","dns-rebinding","url-validation","allowlist"],"_resolved":"/tmp/d24eb2b1dd0aec5c7444acba8e9aae29/advance-labs-net-guard-0.2.2.tgz","_integrity":"sha512-Iy0orK8wvoZvsLh75ThR0stRojO87VFPJuIsCPaBEuGJw+37bjZlsKpyTmP/L3HlssuDMD/NPPFy+Y5XoooTLA==","repository":{"url":"git+https://github.com/Advance-Labs/aeo-toolkit.git","type":"git","directory":"packages/net-guard"},"_npmVersion":"11.19.0","description":"SSRF-guarded HTTP fetch seam — DNS-resolves and rejects private/loopback/link-local/CGNAT/cloud-metadata addresses, re-validates every redirect hop, caps body size and time, and host-pins to defeat DNS rebinding.","directories":{},"maintainers":[{"name":"zordhalo","email":"lucas@advancelabs.dev"}],"_nodeVersion":"24.20.0","dependencies":{"@advance-labs/types":"0.2.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.3.5","rimraf":"^6.0.1","vitest":"^3.2.6","typescript":"^5.7.2","@types/node":"^22.10.2","@advance-labs/config":"0.1.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/net-guard_0.2.2_1789020836963_0.9819331615101594"}}},"time":{"created":"2026-08-30T03:13:47.433Z","modified":"2026-09-10T06:13:57.232Z","0.2.0":"2026-08-30T03:13:47.736Z","0.2.1":"2026-09-10T05:52:32.993Z","0.2.2":"2026-09-10T06:13:57.040Z"},"bugs":{"url":"https://github.com/Advance-Labs/aeo-toolkit/issues"},"license":"Apache-2.0","homepage":"https://docs.advancelabs.dev/aeo-toolkit","keywords":["ssrf","security","fetch","http","dns-rebinding","url-validation","allowlist"],"repository":{"url":"git+https://github.com/Advance-Labs/aeo-toolkit.git","type":"git","directory":"packages/net-guard"},"description":"SSRF-guarded HTTP fetch seam — DNS-resolves and rejects private/loopback/link-local/CGNAT/cloud-metadata addresses, re-validates every redirect hop, caps body size and time, and host-pins to defeat DNS rebinding.","maintainers":[{"name":"zordhalo","email":"lucas@advancelabs.dev"}],"readme":"# @advance-labs/net-guard\n\nSSRF-guarded HTTP fetch seam. Closes finding **C1** of the Autopilot security review: the existing\ncrawler/backlinks HTTP layer follows redirects with no private-IP guard, so a user-supplied URL can\nreach `169.254.169.254` (cloud metadata), `localhost`, or RFC-1918 hosts.\n\n## Use it for any untrusted URL\n\n```ts\nimport { safeFetch, createLiveSafeFetchDeps } from '@advance-labs/net-guard';\n\nconst deps = createLiveSafeFetchDeps();\nconst res = await safeFetch('https://prospect.example/', {}, deps);\nif (!res.ok) {\n  // res.blockedReason: 'scheme-not-allowed' | 'private-address' | 'dns-resolution-failed'\n  //                  | 'too-many-redirects' | 'body-too-large' | 'timeout'\n}\n```\n\n## What it guards (in order)\n\n1. **Scheme allowlist** — `http:` / `https:` only (rejects `file:`, `gopher:`, …).\n2. **DNS resolve + private-address rejection** — refuses if **any** resolved IP is loopback,\n   RFC-1918, link-local (incl. the metadata IP), CGNAT, IPv6 ULA/link-local, or an IPv4-mapped\n   private address. Malformed addresses **fail closed**.\n3. **Per-hop redirect re-validation** — redirects are manual; the full check re-runs on every target,\n   so a public host can't 302 you to an internal one.\n4. **Body + time caps** — `maxBodyBytes` (default 2 MB) and `timeoutMs` (default 10 s, aborts the request).\n\nAll logic is pure and injected (`resolve`, `fetchImpl`) — unit-tested with zero network. See\n[`docs/CONVENTIONS.md`](../../docs/CONVENTIONS.md) security invariant #1.\n","readmeFilename":"README.md","author":{"url":"https://advancelabs.dev/lucas","name":"Lucas Krawczak","email":"lucas@advancelabs.dev"}}