Area: pipes · policy — security (SQL injection / escaping bypass) · found via pre-launch audit
Expected: the docs promise a pipe parameter value "can't break out of its literal and inject SQL," and a type: number parameter rejects a non-number.
Actual: internal/pipes/pipes.go formatParamValue — the default: branch (:230, fmt.Sprintf("%v", v)) emits raw, unescaped text. Scalar strings are escaped (\→\\, '→'') and scalar numbers are digits-only, so they're safe — but a JSON array or object value hits default: raw ([evil] / map[k:v]). BindParams reads only Required/Default and never checks ParamDef.Type, returning a nil bind slice (pure string interpolation, no driver ? params). internal/api/pipes.go decodes the POST into map[string]any and passes values verbatim; GET/POST /v1/pipes/{name} are outside RequireAdmin (authz is per-pipe allowed_roles, commonly [public] → unauthenticated). In a string-context pipe (WHERE col = '{{p}}') an array element's inner ' terminates the literal → clean UNION/boolean injection that bypasses the column allowlist.
Impact: latent on Stats today (the only parameterized pipe interpolates {{limit}} in a numeric LIMIT least({{limit}},50) context, so an array is a CH type error — yielding a full-pipe-SQL information disclosure in the echoed 500 rather than exfil), but one string-context public pipe away from a live unauth column-allowlist bypass. The structured-query path is unaffected (positional ? binds + per-column gating), so pipes are the one inlined-SQL surface. Re-verified fmt.Sprintf("%v") default branch on 40619b8a.
Scope: enforce ParamDef.Type in BindParams; escape or reject non-scalar values.
Related: #32 (this is the security core of Native SQL Templating — #32's own injection review only analyzed scalar inputs and missed the non-scalar breakout), the pipe cache-bypass issue.
From WaveHouse-Stats pre-launch security audit (WAVEHOUSE-FEEDBACK.md dogfooding), audited dev 60fed15; re-verified live on 40619b8a (2026-06-10). Full repro (payloads, local CH exfil of denied actor_id, live marker echo): docs/security/pipe-param-injection-poc.md (private). Filed via /pm-triage.
Area: pipes · policy — security (SQL injection / escaping bypass) · found via pre-launch audit
Expected: the docs promise a pipe parameter value "can't break out of its literal and inject SQL," and a
type: numberparameter rejects a non-number.Actual:
internal/pipes/pipes.goformatParamValue— thedefault:branch (:230,fmt.Sprintf("%v", v)) emits raw, unescaped text. Scalar strings are escaped (\→\\,'→'') and scalar numbers are digits-only, so they're safe — but a JSON array or object value hitsdefault:raw ([evil]/map[k:v]).BindParamsreads onlyRequired/Defaultand never checksParamDef.Type, returning anilbind slice (pure string interpolation, no driver?params).internal/api/pipes.godecodes the POST intomap[string]anyand passes values verbatim;GET/POST /v1/pipes/{name}are outsideRequireAdmin(authz is per-pipeallowed_roles, commonly[public]→ unauthenticated). In a string-context pipe (WHERE col = '{{p}}') an array element's inner'terminates the literal → cleanUNION/boolean injection that bypasses the column allowlist.Impact: latent on Stats today (the only parameterized pipe interpolates
{{limit}}in a numericLIMIT least({{limit}},50)context, so an array is a CH type error — yielding a full-pipe-SQL information disclosure in the echoed 500 rather than exfil), but one string-context public pipe away from a live unauth column-allowlist bypass. The structured-query path is unaffected (positional?binds + per-column gating), so pipes are the one inlined-SQL surface. Re-verifiedfmt.Sprintf("%v")default branch on40619b8a.Scope: enforce
ParamDef.TypeinBindParams; escape or reject non-scalar values.Related: #32 (this is the security core of Native SQL Templating — #32's own injection review only analyzed scalar inputs and missed the non-scalar breakout), the pipe cache-bypass issue.
From WaveHouse-Stats pre-launch security audit (
WAVEHOUSE-FEEDBACK.mddogfooding), audited dev60fed15; re-verified live on40619b8a(2026-06-10). Full repro (payloads, local CH exfil of deniedactor_id, live marker echo):docs/security/pipe-param-injection-poc.md(private). Filed via /pm-triage.