islandflow/piolium/attack-surface/manual-attack-surface-inventory.md
dirtydishes 47a5adca90
Some checks failed
CI / Validate (pull_request) Has been cancelled
Add attack surface audit artifacts
- Add advisory, entrypoint, and candidate scan outputs
- Capture dependency intelligence and cross-service attack surface notes
2026-05-28 05:13:36 -04:00

3.6 KiB

Manual Attack Surface Inventory (Stage 08)

Highest-impact slices selected

  1. Synthetic admin control: public Next.js route handlers proxy to API admin endpoints with server bearer token.
  2. Provider/news HTML to browser DOM: Alpaca content is stored and later rendered through a regex sanitizer and dangerouslySetInnerHTML.
  3. Live WebSocket/API market data exposure: public WS upgrades and history reads have no handler-level auth/origin checks.
  4. Root Docker Compose infrastructure: ClickHouse, Redis, and NATS are published on host ports without credentials in the compose file.

Public routes / URLs

  • Next admin proxy: GET /api/admin/synthetic/status, GET/PUT /api/admin/synthetic/control (apps/web/app/api/admin/synthetic/status/route.ts:5-7, apps/web/app/api/admin/synthetic/control/route.ts:5-17).
  • API admin backend: GET /admin/synthetic/status, GET/PUT /admin/synthetic/control (services/api/src/index.ts:1364-1388).
  • API history/news and related reads: /history/news (services/api/src/index.ts:1656-1660) plus other unauthenticated history/replay/read endpoints documented in P5 matrix.
  • WebSockets: /ws/options, /ws/options-nbbo, /ws/equities, /ws/equity-candles, /ws/equity-quotes, /ws/equity-joins, /ws/inferred-dark, /ws/flow, /ws/classifier-hits, /ws/smart-money, /ws/alerts, /ws/live (services/api/src/index.ts:1846-1936).
  • Host infra ports from root compose: ClickHouse HTTP/native 8123/9000, Redis 6379, NATS client/monitor 4222/8222 (docker-compose.yml:4-24).

Attacker-controlled sources

  • Anonymous browser requests to Next route handlers when NEXT_PUBLIC_SYNTHETIC_ADMIN=1.
  • HTTP query/path parameters and WebSocket connection/message bytes to the API.
  • Alpaca/provider news item.content, item.summary, item.url, and symbols before persistence/display.
  • Network clients reaching published compose ports on the host.
  • Environment hidden controls: NEXT_PUBLIC_API_URL, SYNTHETIC_ADMIN_TOKEN, API_HOST, compose deployment choice.

Sinks

  • NATS KV write of synthetic control state through API admin PUT (services/api/src/index.ts:1386-1388).
  • Browser DOM HTML sink: dangerouslySetInnerHTML for news story body (apps/web/app/terminal.tsx:5009).
  • WebSocket serverRef.upgrade and live snapshots (services/api/src/index.ts:1847-1935, 1982-2008).
  • ClickHouse query reads for history/replay (services/api/src/index.ts:1556-1660, storage package).
  • Direct ClickHouse/Redis/NATS network services from root compose (docker-compose.yml:4-24).

Hidden control channels

  • NEXT_PUBLIC_SYNTHETIC_ADMIN enables/disables admin proxy; NEXT_PUBLIC_API_URL chooses the privileged proxy target; SYNTHETIC_ADMIN_TOKEN is injected server-side (apps/web/app/api/admin/synthetic/shared.ts:10-22, 44-55).
  • API admin accepts either bearer token or x-synthetic-admin-token fallback (services/api/src/index.ts:320-333).
  • API exposure depends on API_HOST/reverse proxy rather than handler auth; WS routes do not inspect Origin.
  • Root compose vs production compose changes infra from internal-only to host-published.

Exploit-relevant paths

  • Browser -> Next /api/admin/synthetic/control -> server injects bearer -> API admin -> NATS KV synthetic control mutation.
  • Provider news HTML -> content_html -> ClickHouse/API /history/news -> React drawer -> regex sanitizer -> dangerouslySetInnerHTML.
  • Remote WS client -> /ws/live upgrade -> subscribe message -> liveState.getSnapshot -> live/research data stream.
  • Network client -> host port 4222 NATS -> publish forged subjects / KV updates; or 8123/9000 ClickHouse -> query/alter data; or 6379 Redis -> read/write cache.