Skip to content

Ingest routes return 403 for agents running inside Docker (host.docker.internal) since v0.1.10 #33

Description

@jmwind

Since v0.1.10, Workshop rejects all SDK traffic from apps running inside Docker containers. Containers reach the host's Workshop via RAINDROP_LOCAL_DEBUGGER=http://host.docker.internal:5899/v1/, so their requests carry Host: host.docker.internal:5899. The hardening added in v0.1.10 (isAllowedLocalAccess in src/server.ts) only accepts localhost/127.0.0.1 as the Host header — including on the ingest paths — so every trace/event POST gets 403 {"error":"forbidden"} and telemetry silently never appears in Workshop. This worked in ≤ v0.1.8.

Running the agent app in Docker Compose while Workshop runs on the host is a common local dev setup, and there's currently no escape hatch (RAINDROP_WORKSHOP_ALLOWED_ORIGINS only extends the browser Origin check, not the Host check).

Repro (macOS, Docker Desktop, Workshop v0.1.15)

raindrop workshop on the host (default port 5899). curl http://localhost:5899/health → 200.
From any container:
docker run --rm node:22-slim node -e "
fetch('http://host.docker.internal:5899/v1/traces',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify({resourceSpans:[]})}).then(async r=>console.log(r.status, await r.text()))"
Actual: 403 {"error":"forbidden"} (on v0.1.15). Expected: 200 {"ok":true,...} (as on v0.1.8).

That it's the Host header, not the socket: the same request from inside the container with the header forced to Host: localhost:5899 returns 200 — the socket-level loopback check passes (Docker Desktop proxies via loopback), only isAllowedLocalAccess rejects it.

Suggested fix, or we are open to a workaround as well.

Allow host.docker.internal on the ingest paths, or add something like RAINDROP_WORKSHOP_ALLOWED_HOSTS mirroring RAINDROP_WORKSHOP_ALLOWED_ORIGINS. The socket-level loopback enforcement already prevents LAN access, so relaxing the Host check for ingest shouldn't reopen that hole on Docker Desktop-style setups.

Workaround we're using: pinned to v0.1.8.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions