Skip to content

0.27.2

  • 0.27.2
  • 2d3af44
  • Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
  • Choose a tag to compare

  • 0.27.2
  • 2d3af44
  • Choose a tag to compare

  • Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
@dnukumamras dnukumamras tagged this 30 Jun 13:31
## What

Adds an SSRF guard for server-side image loads.

Satori resolves `<img src>`, SVG `<image href>` and CSS
`background-image` URLs by calling `fetch()` on the server. Without a
guard, an attacker who controls one of those URLs can point it at
internal addresses (`127.0.0.1`, `169.254.169.254` cloud metadata,
RFC-1918 ranges) and — because SVG responses are base64-inlined into the
output — read the body back in-band.

## Changes

- **`src/handler/url-safety.ts`** (new): dependency-free,
runtime-agnostic literal-host classifier. Blocks loopback,
link-local/metadata, RFC-1918, CGNAT, multicast/reserved, and the IPv6
equivalents. Leans on WHATWG `URL` to normalize obfuscated IPv4 forms
(`0x7f000001`, `2130706433`, `127.1`) and decodes IPv4 embedded in IPv6
(mapped `::ffff:`, NAT64 `64:ff9b::`, compatible `::`). Fails closed on
unparseable input and non-`http(s)` protocols.
- **`src/handler/image.ts`**: runs the guard server-only before
fetching. **Fails closed (throws)** — consistent with the existing
absolute-URL validation.

## Scope / known limits

- The guard is **literal-host only**. Hostnames that resolve to private
IPs (DNS rebinding) and HTTP redirects to private addresses are **not**
covered — full coverage needs a connect-time-pinning fetcher (e.g.
`@vercel/safe-fetch`) at the host layer. Documented in the module
header.
- A pluggable `fetcher` option was removed per review (`typeof fetch`
isn't compatible with safe-fetch libraries' redirect policing); it can
be added later with a compatible signature.

## Tests

- `test/url-safety.test.ts`: reported SSRF vectors, obfuscated IPv4,
NAT64/IPv4-compatible IPv6, non-`http(s)` protocols, and public URLs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Assets 2
Loading