What happened

GET /nodes, GET /node/{id}, and SSE /sse all serialize a node’s full meta object to any caller holding the cluster bearer token. Two SDK meta types carry a live, user-configured credential as one of their fields: the SMTP executor’s outbound-mail password, and the outgoing-webhook executor’s auth-shaped HTTP header values (e.g. a bearer/API-key header the user added). The SDK’s own KDoc on those fields says “stored server-side; never sent to read clients” — but nothing in the server actually enforced that. Every bearer-holding read caller (the Compose UI, an MCP agent, or — on a public-demo deployment (krill#915) — anyone) received the plaintext credential value in the response body.

Root cause

Pre-existing since these node types shipped — not a regression. /nodes, /node/{id}, and /sse all serialize whatever Node the persistence layer hands back, with no distinction between “fields safe to echo to a read client” and “fields that exist only so the server itself can act on them.”

Fix

Prevention