Releases: devslab-kr/ssrf-guard-js
Release list
v0.4.0
Added
guardedFetch— a runtime-agnostic guarded fetch for environments that
cannot runsafeFetch's DNS checks (Cloudflare Workers, browsers, edge
runtimes). Same redirect revalidation, cross-origin credential stripping,
and303/301/302-POSTmethod-downgrade semantics assafeFetch,
minus DNS resolution and IP pinning — the policy allowlist is the primary
control. Accepts afetchImploverride for tests and instrumented clients.sameSitePolicy(url, overrides?)— derives aUrlPolicyOptionsallowlist
from a submitted URL, locking the whole fetch (redirects included) to that
domain with a leadingwww.stripped. Overrides merge additively, so
extra hosts can be allowlisted alongside.
Changed
node:dnsis now imported lazily. Importing the package no longer
requires a functionalnode:dnsmodule — on runtimes without one,
safeFetchthrows a typedSsrfGuardErrordirecting callers to
guardedFetchinstead of failing at module load.safeFetchandguardedFetchshare one redirect-revalidation loop
(internal refactor; behavior unchanged, covered by the existing suite).
v0.3.0
Added
- Optional DNS pinning for
safeFetch, closing the DNS-rebinding TOCTOU
window. When the optionalundicipeer dependency is installed, the
resolved addresses are validated inside the socket connector, so the
check and the connection share a single DNS resolution. New
pinDnsoption:truerequires pinning (throws withoutundici),
falsedisables it, unset pins automatically whenundiciis available.
v0.2.0
Stricter-by-default release. Things that may need attention when upgrading:
- Tool inputs containing non-http
scheme://URLs (e.g.s3://, custom
protocols) are now flagged unless the scheme is inallowedSchemes. - Hosts whose DNS answer mixes public and private addresses are now blocked
bysafeFetch(previously allowed if any address was public). safeFetchno longer replaysAuthorization/Cookieheaders or request
bodies across cross-origin redirects — if you depended on that, send the
follow-up request explicitly.
Security
safeFetch/assertResolvedIpsAllowednow fail closed when any
resolved DNS address is private/local. Previously the request was allowed as
long as at least one address was public, so an attacker-controlled DNS
record returning a mixed public + private answer could pass the check while
the actual connection used the private address.safeFetchno longer forwards credentials across origins:Authorization,
Proxy-Authorization, andCookieheaders are stripped when a redirect
changes the origin.safeFetchnow follows the fetch spec's redirect semantics:303(and
301/302forPOST) downgrade toGETand drop the request body instead
of replaying it against the redirect target.- The tool-input URL scanner now collects any
scheme://URL (not just
http/https), sofile://,ftp://, andgopher://URLs in tool input
are validated and rejected by the policy'sallowedSchemesinstead of
passing the guard silently. Protocol-relative//hoststrings are also
collected and validated against the host policy. Authority-less schemes
(mailto:,urn:,data:) remain ignored.
Changed
- Portless URLs now count as the scheme's default port (
http/ws→80,
https/wss→443) for theallowedPortscheck, so
allowedPorts: [443]alone works for HTTPS-only policies.-1still
matches portless URLs of schemes without a known default.
Fixed
safeFetchcancels redirect response bodies before following the next hop,
releasing the underlying connection.SsrfGuardErrorthrown for unparseable URLs now preserves the original
parse error ascause.
v0.1.2 — security fix
Security
Fixed a guard bypass where URLs with uppercase or mixed-case schemes (HTTP://, Https://, ...) were not collected by the tool-input scanner and therefore skipped policy validation entirely.
Affected: guardToolInput, guardToolInputJson, createGuardedToolHandler, createExpressUrlGuard, ssrfGuardVitePlugin.
Not affected: validateUrl and safeFetch already lowercased the scheme before checking it.
Scheme detection is now case-insensitive, matching WHATWG URL scheme semantics. If you use any of the affected entry points to guard LLM tool inputs or HTTP request parameters, upgrade to 0.1.2.
guardToolInput({ url: 'HTTP://169.254.169.254/latest/meta-data/' })
// 0.1.1: null (bypass)
// 0.1.2: { error: 'ssrf_blocked', reason: 'blocked_ip_literal', ... }
Full changelog: https://github.com/devslab-kr/ssrf-guard-js/blob/main/CHANGELOG.md
v0.1.1
v0.1.0
Initial release: UrlPolicy / validateUrl (scheme, host allowlist, port, userinfo, IP-literal checks), private-network IP classification, safeFetch with DNS and redirect re-validation, LLM tool-input guards, Express middleware, and a Vite dev-server plugin.