Repository navigation
security(streaming): applyStreamPolicy passes non-EventMessage / empty table_name payloads through unfiltered (fail-open) #323
Description
Activity
- addedarea/observabilityMetrics, logs, traces, health, profilingMetrics, logs, traces, health, profilingarea/apiHTTP handlers, routing, middlewareHTTP handlers, routing, middlewaresecuritySecurity-sensitive issue or fixSecurity-sensitive issue or fix
on Jun 10, 2026 coderabbitai commented
on Jun 10, 2026 coderabbitaiboton Jun 10, 2026 – with coderabbitaiMore actions🔗 Related PRs
#124 - chore(api)!: drop hub wildcard fan-out; SSE/WS use ?table= (closes
#100) [merged]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.- Create Plan
🧪 Issue enrichment is currently in open beta.
You can configure auto-planning by selecting labels in the issue_enrichment configuration.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:issue_enrichment: auto_enrich: enabled: false
💬 Have feedback or questions? Drop into our discord!
- addedarea/policyAccess control policies (Hasura-style)Access control policies (Hasura-style)bugSomething isn't workingSomething isn't working
on Jun 10, 2026 - addedarea/streamingSSE / live-query delivery path (/v1/stream)SSE / live-query delivery path (/v1/stream)
on Aug 3, 2026 Status from the #457 review — this is fixed; only a test is missing.
The function named here,
applyStreamPolicy, no longer exists. It was dissolved intoproject()by ccd7549 ("perf(stream): project SSE frames once per role, not per subscriber", #353, 2026-07-06). The fail-closed default came along as a side effect of moving the decode out of the per-subscriber loop, which is why nothing linked it back here.Both conditions in this issue's title collapse into one flag at
internal/stream/hub.go:160:decoded := json.Unmarshal(raw, &evt) == nil && evt.TableName != ""
!decodedthen routes into the guard at:180-189, which returnsnil, falsewhenever a policy store is wired. Both call sites go through it —Broadcast(live,:129) andReplayFrame(replay,:162). Verified by execution:empty table_name, policy wired -> dropped (fail closed) missing table_name, policy wired -> dropped (fail closed) non-EventMessage, policy wired -> dropped (fail closed) empty table_name, NO policy wired -> DELIVERED (intended: no policy to apply)The trigger is also unreachable today by construction: the only producer rejects an empty table with
400 missing table(internal/api/ingest.go:128) before publishing, and the embedded NATS server has no network listener at all (internal/mq/embedded.go:60,DontListen: true) — there is no external-NATS mode, so no second producer can exist.Remaining work:
hub_test.go:188pins only the non-EventMessagehalf. The empty-table_namehalf rests entirely on the seven characters&& evt.TableName != ""; delete them and half of this issue silently returns with the suite green. #457 adds that regression test and will close this issue on merge.- moved this from Backlog to In progress in WaveHouse Task Board
on Aug 12, 2026
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Area: api · observability (streaming) — security (defense-in-depth, fail-open) · found via pre-launch audit
Expected: every message on the stream path is policy-filtered, including malformed or edge payloads (fail closed).
Actual:
applyStreamPolicypasses a non-EventMessageor empty-table_nameJSON payload through unfiltered (no policy applied). Not publicly reachable on Stats today, but a fail-open default: an unexpected payload shape skips filtering instead of failing closed.Impact: low (the broadcast source is internal), but the wrong default direction for a policy gate — a future bug or new producer that emits an off-shape payload would bypass filtering silently.
Scope: fail closed on un-typed / empty-
table_namepayloads.Related: #294 (SSE delivery path), the SSE row-filter drift issue.
From WaveHouse-Stats pre-launch security audit (
WAVEHOUSE-FEEDBACK.mddogfooding), audited dev60fed15(2026-06-10). Filed via /pm-triage.