Skip to content

Persistent SSRF allowlist + admin UI + test fix hint (#2)#166

Merged
keysersoft merged 1 commit into
mainfrom
keysersoft/ssrf-allowlist-ui
May 12, 2026
Merged

Persistent SSRF allowlist + admin UI + test fix hint (#2)#166
keysersoft merged 1 commit into
mainfrom
keysersoft/ssrf-allowlist-ui

Conversation

@keysersoft
Copy link
Copy Markdown
Contributor

Problem

`SSRF_ALLOWED_HOSTS` was a backend env var only. Onboarding a connector that calls a service on the internal network — e.g. a docker-compose sibling like `koch-filesystem-bridge` (a real customer case) — required editing the env, restarting, and there was nothing in the UI explaining the failure or how to fix it.

Changes

Backend

  • `SsrfPolicyService` (`common/ssrf-policy.service.ts`) — merges `SSRF_ALLOWED_HOSTS` env var with a DB-backed list stored in `SiteSettings` (`ssrf_allowed_hosts` key, JSON array). Cached in-process for 60s; `invalidate()` flushes after writes.
  • `ssrf.util.ts` — new `setDbAllowedHostsProvider()` hook. `SsrfPolicyService.onModuleInit` wires itself in, so every `assertSafeOutboundUrl` call consults both layers. No-op when the service isn't loaded (preserves existing unit tests).
  • Admin API: `GET` / `PUT /api/admin/settings/ssrf-allowed-hosts`. `PUT` validates host shape — accepts hostnames, `*.suffix` wildcards, and bare IPs; rejects URLs / whitespace / control chars.
  • Connector test response now carries a `suggestedFix` object when the failure is specifically the SSRF guard:
    ```json
    { "action": "add-to-ssrf-allowlist", "hostname": "koch-filesystem-bridge", "url": "/admin/settings#ssrf" }
    ```

Frontend

  • New 'SSRF allowlist' section in `/admin/settings` with a red warning, env-var hosts shown read-only, and a textarea for the editable list.
  • Connector detail test-result banner renders `suggestedFix` as a click-through link: 'Add `` to the SSRF allowlist'.

Security notes

  • Restricted to org-level `ADMIN` via existing `RolesGuard`.
  • UI has explicit warning copy: 'anything added here can be reached by every connector in every organization on this deployment'.
  • The 60s cache means a freshly-added host takes up to a minute to apply across long-running processes. Acceptable trade-off vs. hitting DB on every outbound URL.
  • Env-only setups continue to work unchanged.

Test plan

  • `SsrfPolicyService.spec.ts` — 7 unit tests (env-only, merge, persist, cache TTL + invalidate, invalid host, accepted shapes, DB-failure fallback).
  • `tsc --noEmit` exit 0 on backend and frontend.
  • Full backend test suite: 631 passed across 26 suites.
  • After deploy: as admin, hit `/admin/settings`, add a host, save, then test a connector pointing at it.
  • After deploy: import a connector pointing at an internal-network hostname, hit Test → expect red banner with 'Add … to the SSRF allowlist' link.

Before this, SSRF_ALLOWED_HOSTS could only be set as a backend env var.
Deploying a new connector against a service on the internal network
(e.g. a docker-compose sibling like 'koch-filesystem-bridge') required
editing the env, restarting the container, and praying.

Now:

- New SsrfPolicyService merges the env var with a DB-backed list
  stored in SiteSettings ('ssrf_allowed_hosts' key, JSON array). The
  list is cached in-process for 60s and re-read after each write
  through invalidate().

- ssrf.util.ts exposes setDbAllowedHostsProvider(); the policy service
  wires itself in via onModuleInit so every assertSafeOutboundUrl call
  consults both layers. No-op if the service isn't loaded (unit tests).

- New admin API: GET / PUT /api/admin/settings/ssrf-allowed-hosts.
  PUT validates host shape (no URLs, no whitespace, allows hostnames,
  *.suffix wildcards, and bare IPs).

- Frontend admin settings page: new 'SSRF allowlist' section with a
  red warning, the env-var list shown read-only, and a textarea for
  the admin-editable list.

- Connector test response carries a suggestedFix:
    { action: 'add-to-ssrf-allowlist', hostname, url }
  when the failure was the SSRF guard rejecting an internal hostname.
  The connector detail UI renders this as a click-through to
  /admin/settings#ssrf.

Tests: SsrfPolicyService spec (7 cases). Full backend suite green
(631 passed). Frontend tsc clean.
@keysersoft keysersoft requested a review from mirkopoloni as a code owner May 12, 2026 07:34
Comment thread packages/frontend/src/app/admin/settings/page.tsx Dismissed
@keysersoft keysersoft merged commit 0f454f9 into main May 12, 2026
11 checks passed
@keysersoft keysersoft deleted the keysersoft/ssrf-allowlist-ui branch May 12, 2026 07:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants