Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Do not "fix" the second group by adding the guard: that breaks normal installs.

Each of the four owns the whole pipeline: **rewrite, then guard the rewritten URL, then connect to it.** A ping therefore reports on the same target the matching fetch would use. Callers never handle the intermediate URL, so the URL that is checked cannot drift away from the URL that is connected to. Keep the guard downstream of every URL transformation: if a rewrite step is ever added, it goes above the guard.

The guard resolves the target host and rejects private, loopback, and link-local addresses via `PRIVATE_IP_RE` (unless `ALLOW_PRIVATE_IPS` is set), then pins the resolved IP so the connection cannot be re-pointed after the check. A blocked request throws `SsrfBlockedError`, which carries `status: 403` so a route's `catch` can forward it. `fetchJSON` itself disables redirect following, enforces a 4 MB response cap, applies per-request timeouts, and decides TLS verification through `shouldSkipTls`. `rewriteUrl` maps the container host IP back to a container name so links that work in the browser also work from inside the network. The `parse-prometheus.js` and `parse-xml.js` modules let widget handlers consume non-JSON upstreams; they hold no network logic, so they live outside this boundary and are tested on their own.
The guard resolves the target host and rejects it with `isPrivateAddress`, which tests the address against the `BLOCKED_IPV4` CIDR table (private, loopback, link-local including cloud metadata, carrier-grade NAT, multicast, reserved and broadcast, benchmarking, and IETF protocol assignments) and `BLOCKED_IPV6_RE` (loopback, unspecified, unique local, link-local, multicast), unwrapping IPv4-mapped IPv6 forms first; `localhost` is refused by name. All of it is skipped when `ALLOW_PRIVATE_IPS` is set. The resolved IP is then pinned so the connection cannot be re-pointed after the check. A blocked request throws `SsrfBlockedError`, which carries `status: 403` so a route's `catch` can forward it. `fetchJSON` itself disables redirect following, enforces a 4 MB response cap, applies per-request timeouts, and decides TLS verification through `shouldSkipTls`. `rewriteUrl` maps the container host IP back to a container name so links that work in the browser also work from inside the network. The `parse-prometheus.js` and `parse-xml.js` modules let widget handlers consume non-JSON upstreams; they hold no network logic, so they live outside this boundary and are tested on their own.

## Summary

Expand Down
Loading