If you discover a security vulnerability, please report it privately:
- Do not open a public issue
- Email: security@luigiagosti.com (or open a private security advisory on GitHub)
- Include details about the vulnerability and steps to reproduce
We will respond within 48 hours and work with you to understand and fix the issue.
SeaPortal fetches attacker-controlled URLs (and, in stdin mode, attacker-controlled HTML), so any service that calls it on untrusted input inherits a server-side request surface. The fetch path defends against:
- SSRF / private-IP access — targets that resolve to RFC1918, loopback,
link-local, ULA, carrier-grade-NAT, unspecified/multicast, or the cloud
metadata endpoint (
169.254.169.254) are rejected. The check runs both pre-fetch (on the resolved IP) and at the dial Control hook (the concrete post-DNS IP), which closes the DNS-rebinding TOCTOU window. - Redirect-to-internal SSRF — every redirect hop is re-validated
(scheme + host + resolved IP) when
RevalidateRedirectsis set, so a public URL cannot bounce to an internal one. Hops are capped byMaxRedirects. - Scheme abuse — only
http/httpsare dialled by default;file:,ftp:,gopher:,ws:, etc. are rejected. (data:is decoded in-process and never touches the network.) - Decompression bombs & oversized bodies — the raw response and the
decompressor output (gzip/br/deflate/zstd) are each bounded
(
MaxResponseBytes/MaxDecompressedBytes), failing closed instead of OOM. - Domain allow/deny — optional allowlist / blocklist on the target host.
- Robustness — malformed URLs and malicious HTML must not crash or hang; timeouts and retries are bounded.
These are governed by an opt-in SecurityPolicy (see
api.md and cli.md).
DefaultSecurityPolicy() is the sane-by-default posture and is applied
automatically by the CLI and the MCP server (the most exposed
entrypoint). Library callers via seaportal.FromURL* opt in by setting
Options.Security — a nil policy preserves the historical unguarded
behaviour, so embedding code must set a policy when handling untrusted URLs.
SeaPortal can present a Chrome TLS fingerprint (uTLS) to reach sites that
fingerprint Go's TLS stack. This is for reachability, not deception of
operators: the cooperative, well-behaved mode is --ua=seaportal plus
--respect-robots, which identifies the fetcher and honours robots.txt.
Choose the fingerprint posture deliberately for your use case.
--proxy/Options.Proxy— the dial-time IP re-check (the DNS-rebinding guard) only runs on the direct path, since a proxied request dials the proxy, not the target. The target host is still vetted pre-fetch and on every redirect (scheme + domain + resolved IP), just not at connect time.--snapshot(CLI) — the snapshot-from-URL path uses a lighter HTTP client. It pre-validates scheme + host + resolved IP, but does not apply the redirect re-validation or the response/decompression size caps. Prefer the main extract path for untrusted input.- Library default is
nil= unguarded — see above; only the CLI and MCP are safe by default.
| Knob | Default |
|---|---|
BlockPrivateIPs |
true |
AllowedSchemes |
http, https |
MaxRedirects |
10 (0 = none, -1 = unlimited) |
RevalidateRedirects |
true |
MaxResponseBytes |
50 MiB (0 = unlimited) |
MaxDecompressedBytes |
200 MiB (0 = unlimited) |
AllowedDomains / DeniedDomains / TrustedResolveCIDRs |
empty |
Only the latest release is supported with security updates.