# Risk map — firecrawl/firecrawl

> Canonical page: https://codevetter.com/unpack/firecrawl/risk-map

# Risk map — firecrawl/firecrawl

Scanned commit 556c12c9d293bc7392feb008946944d54068d04c (2026-09-21). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

The highest blast radius sits in the auth/credit middleware chain and the scrapeURL pipeline: both are fail-open in places (Autumn outage, missing org_id) and carry many security gates that must run in the right order. Keyless free-tier abuse is mitigated by IPv4-only identity and Spur checks but is inherently risky. Shell-out exists in harness.ts (container commands are escaped) and via koffi FFI to a native lib. Secrets flow through env config; SIEM/webhook/ZDR paths handle sensitive customer data. Legacy BullMQ code, v0/v1 routers, and parallel PG/FDB queue backends add maintenance surface.
- checkCreditsMiddleware deliberately fails open when Autumn returns null and when req.auth.org_id is absent (keyless/preview/DB-auth bypass), so an Autumn outage or missing org mapping grants unlimited credits — explicitly commented as intentional to avoid customer outage. — [apps/api/src/routes/shared.ts#L157-190](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/routes/shared.ts#L157-L190)
- Keyless tier trusts a forwarded client IP only when x-firecrawl-keyless-secret matches KEYLESS_PROXY_SECRET; IPv6 clients are refused outright and Spur screening is optional (disabled without SPUR_API_KEY), so anonymized abuse controls depend on deployment config. — [apps/api/src/controllers/auth.ts#L513-543](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/controllers/auth.ts#L513-L543) [apps/api/src/config.ts#L101-121](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/config.ts#L101-L121)
- harness.ts shells out to docker/podman with string commands; a shellEscape helper quotes credentials, but commands like `runtime ps --filter name=^${containerName}$` interpolate values — the file itself flags injection concerns in comments. — [apps/api/src/harness.ts#L129-133](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/harness.ts#L129-L133) [apps/api/src/harness.ts#L416-425](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/harness.ts#L416-L425) [apps/api/src/harness.ts#L467-478](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/harness.ts#L467-L478)
- Native FFI: lib/html-to-markdown.ts loads a .so/.dylib via koffi and calls ConvertHTMLToMarkdown on arbitrary scraped HTML; a malformed page or lib bug crashes the process, and GoMarkdownConverter.getInstance throws 'Go shared library not found' when sharedLibs is missing (e.g. partial Docker builds). — [apps/api/src/lib/html-to-markdown.ts#L11-45](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/lib/html-to-markdown.ts#L11-L45) [apps/api/src/natives.ts](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/natives.ts)
- The bull-board admin UI is gated only by knowledge of BULL_AUTH_KEY embedded in the URL path (/admin/<key>/queues); when unset the routes are disabled with a warning, but a leaked key exposes queue contents. — [apps/api/src/index.ts#L100-119](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/index.ts#L100-L119)
- Public unauthenticated endpoints exist by design: /v2/slack/commands + /slack/events (signature-verified), /browser/webhook/destroyed, /monitor/email/confirm + unsubscribe (token in body), /keyless/eligibility (secret-gated in controller), /mcp action-log ingest — each must verify its own credential since no authMiddleware runs. — [apps/api/src/routes/v2.ts#L548-554](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/routes/v2.ts#L548-L554) [apps/api/src/routes/v2.ts#L598-623](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/routes/v2.ts#L598-L623) [apps/api/src/routes/v2.ts#L182](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/routes/v2.ts#L182) [apps/api/src/routes/v2.ts#L663-666](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/routes/v2.ts#L663-L666)
- Zero-data-retention is a cross-cutting invariant: ZDR is resolved early in scrapeController specifically so the root OTel span never records the URL, and processJobInternal wraps execution in withZeroDataRetention; a missed code path anywhere leaks target URLs into traces/logs. — [apps/api/src/controllers/v2/scrape.ts#L63-72](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/controllers/v2/scrape.ts#L63-L72) [apps/api/src/services/worker/scrape-worker.ts#L1776-1796](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/services/worker/scrape-worker.ts#L1776-L1796)
- Scrape pipeline has ~30 distinct error types (error.ts imports in scrapeURL/index.ts) mapped to ad-hoc status codes in the controller catch-block; new TransportableError codes must be added to the mapping or they fall through to generic 500s. — [apps/api/src/scraper/scrapeURL/index.ts#L33-63](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/scraper/scrapeURL/index.ts#L33-L63) [apps/api/src/controllers/v2/scrape.ts#L462-585](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/controllers/v2/scrape.ts#L462-L585)
- Dual queue backends double the worker logic surface: scrape-worker branches on (job as any).backend === 'fdb' for lock extension, queue-jobs routes between scrapeQueue/scrapeQueueFdb/routedScrapeQueue, and nuq-postgres vs nuq-fdb diverge in prefetch/reconciler workers — bugs can affect one backend silently. — [apps/api/src/services/worker/scrape-worker.ts#L1798-1817](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/services/worker/scrape-worker.ts#L1798-L1817) [apps/api/src/services/queue-jobs.ts#L27-35](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/services/queue-jobs.ts#L27-L35) [docker-compose.yaml#L58-60](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/docker-compose.yaml#L58-L60)
- Crawl children bypass request-time gates: discovered URLs rely on worker-side checks (isUrlBlocked post-scrape, checkUrlsAgainstThreatPolicy during link discovery, per-URL safe-mode in scrapeURL) so ordering bugs there would let a seed-approved crawl scrape disallowed pages. — [apps/api/src/services/worker/scrape-worker.ts#L476-501](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/services/worker/scrape-worker.ts#L476-L501) [apps/api/src/controllers/v2/crawl.ts#L115-164](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/controllers/v2/crawl.ts#L115-L164) [apps/api/src/scraper/scrapeURL/index.ts#L1247-1305](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/scraper/scrapeURL/index.ts#L1247-L1305)
- Supabase/Postgres pools are sized against a shared pgbouncer cap ('pods * max' per pool per comments in db/connection.ts); a misconfigured DB_POOL_PROFILE or missing keepWarm behavior can exhaust the 12000-connection pooler budget fleet-wide. — [apps/api/src/db/connection.ts#L28-50](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/db/connection.ts#L28-L50) [apps/api/src/db/pool-profiles.ts](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/db/pool-profiles.ts)
- Deprecated surfaces remain live: v0 router, /v2/extract (deprecationMiddleware), /v2/research and /developer legacy proxies, plus a v1 API surface — each is a maintenance and audit surface that still executes production code paths. — [apps/api/src/routes/v0.ts](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/routes/v0.ts) [apps/api/src/routes/v2.ts#L368-384](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/routes/v2.ts#L368-L384) [apps/api/src/routes/v2.ts#L689-708](https://github.com/firecrawl/firecrawl/blob/556c12c9d293bc7392feb008946944d54068d04c/apps/api/src/routes/v2.ts#L689-L708)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
