Area: api · policy — security (pre-authz existence oracles / info-leak) · found via pre-launch audit
Umbrella for the enumeration / info-disclosure findings from the 2026-06-09 audit. The common root is existence / validation checks running before authorization, so an anonymous caller can distinguish "exists but forbidden" (403) from "doesn't exist" (404/400) and enumerate names/values it shouldn't see. The fix pattern is uniform — authorize before existence, and return an indistinguishable response for forbidden-vs-absent. Promote each checklist item to its own issue when picked up.
Checklist:
Related: #260 (the table-name oracle — already filed, same root: schema-existence 404 echoing the name before authz), #214 (per-table policy scopes), the DoS / resource-exhaustion hardening epic (the value/count scrape also needs rate-limiting).
From WaveHouse-Stats pre-launch security audit (WAVEHOUSE-FEEDBACK.md dogfooding), audited dev 60fed15 / enum-pass 0b62271 (2026-06-10). Filed via /pm-triage.
Area: api · policy — security (pre-authz existence oracles / info-leak) · found via pre-launch audit
Umbrella for the enumeration / info-disclosure findings from the 2026-06-09 audit. The common root is existence / validation checks running before authorization, so an anonymous caller can distinguish "exists but forbidden" (403) from "doesn't exist" (404/400) and enumerate names/values it shouldn't see. The fix pattern is uniform — authorize before existence, and return an indistinguishable response for forbidden-vs-absent. Promote each checklist item to its own issue when picked up.
Checklist:
validateColumn(400 "unknown column") runs beforeauthorize(403 "not allowed"), so an anon caller reconstructs the full physical column list of any readable table, including columns withheld frompublic(e.g. a future telemetry table's hidden IP/geo columns).Store.Get(404) before theRoleAllowed(403) gate; latent here (all pipes are[public], so the live signal is only 200-vs-404) but enumerable across roles for any future private pipe.publicgrant permits arbitraryeq/like/in+count, i.e. an unthrottled boolean/substring scrape over the real corpus; low today (data is public) but a PII oracle the instant a sensitive column joins a public allow-set (ties the rate-limit item in the DoS epic).Related: #260 (the table-name oracle — already filed, same root: schema-existence 404 echoing the name before authz), #214 (per-table policy scopes), the DoS / resource-exhaustion hardening epic (the value/count scrape also needs rate-limiting).
From WaveHouse-Stats pre-launch security audit (
WAVEHOUSE-FEEDBACK.mddogfooding), audited dev60fed15/ enum-pass0b62271(2026-06-10). Filed via /pm-triage.