Captatum is a URL-fetcher that may also run a headless browser — a textbook SSRF and sandbox surface. Security is a first-class concern, not an afterthought.
Please do not open a public GitHub issue for security vulnerabilities.
Report vulnerabilities privately via GitHub's built-in channel: Security tab → "Report a vulnerability" (private vulnerability reporting). This notifies the maintainers confidentially and lets us coordinate a fix and disclosure.
If GitHub private reporting is unavailable, open a plain issue asking a maintainer to contact you privately — do not include vulnerability details in the public issue.
Please include, where possible: a description, steps to reproduce, affected component (egress/Tier-1 fetch, Tier-3 browser sandbox, OAuth, prompt-injection handling, supply chain), and impact. We aim to acknowledge reports within a few days.
Only the latest release line receives security fixes (currently v0.11.0).
Pin to a released tag; main is unreleased and may change.
docs/threat-model.md is the security reasoning and the
list of required controls; docs/contracts.md §"Security
controls" is the contract reference. Key invariants:
- SSRF: every outbound request — Tier-1, Tier-2, every redirect hop, every
Tier-3 browser subresource — routes through one rebinding-proof
guardedFetch(resolve-once → pin-to-IP → revalidate each hop; exhaustive IANA private-IP blocking). - Tier-3 browser: runs in a separate sidecar container (hosted); every browser
request is fulfilled through
guardedFetch(route.fulfill, neverroute.continue), so the browser makes no direct egress. - Auth: the hosted flavor authenticates every
/mcprequest via gateway OAuth (PKCE S256, hash-only token storage, replay-revoking refresh rotation, per-request scope enforcement). - Prompt injection: fetched content is treated as untrusted data, never instructions.
- The local-binary flavor has no authentication and must never be exposed on a network — it is single-user/single-agent, loopback only.
- Tier-1 HTTPS intentionally does not use the TLS fingerprint (it uses a checked-IP Node path to preserve rebinding-proof SSRF).
- Prompt-injection fencing applies to
summary/extract, notoutput: raw. - One disclosed residual: a char-class/metachar ReDoS in extract-schema validation (authenticated callers only, low risk). Tracked for closure with RE2 or a worker timeout.
Dependencies are pinned, open-source, minimal, and held to a 15-day
minimum-release-age gate; pnpm audit --prod is required clean before any hosted
deployment (see docs/dependency-ledger.md). The
browser-sidecar base image is pinned by sha256 digest, and CI/release GitHub
Actions are pinned by commit SHA.