You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
sec(api/plans): validatePlanAccountProviders leaks raw account UUID + DB error into logs (gap left by #946) #965
PR #946 (which closed #944) hardened the createPlan storage-error handling by wrapping call sites #1 (CreatePurchasePlan) and #3 (SetPlanAccounts) with mapCreatePlanStorageError (ErrNotFound -> 404, otherwise a structured log + generic 500 with no raw-error leak).
It left call site #2 unwrapped: the inner GetCloudAccount DB-error path of validatePlanAccountProviders in internal/api/handler_accounts.go (~line 1167-1168) still returns:
returnfmt.Errorf("accounts: failed to get account %s: %w", aid, getErr)
On a DB error there, the non-ClientError propagates up to the router's logging.Errorf("API error: %v", err), which logs the raw account UUID and the raw DB error string. This is a PII / info-leak into logs.
Issue #944(b) explicitly required structured logs carrying the account count, not IDs, and "never raw account IDs". The user-facing body is already a generic 500 (the leak is log-side only), but the log line is the gap.
Scope
validatePlanAccountProviders is shared by both createPlan (POST /plans) and setPlanAccounts (PUT /plans/:id/accounts), so the fix applies to both.
Fix
Wrap the GetCloudAccount DB-error case so it (a) emits a structured logging.Errorf with provider/service/account-COUNT (never the UUID), and (b) returns a generic 500 ClientError ("failed to validate plan accounts") carrying no raw UUID or DB string. Reuse the existing mapCreatePlanStorageError helper. Keep ErrNotFound -> 404 (account-not-found must still 404).
Regression test
Assert that a DB error in the provider-validation path yields a 500 whose error message and the emitted log contain neither the account UUID nor the raw DB error string, and that account-not-found still returns 404.
Activity
sec(api/plans): stop leaking raw account UUID + DB error in plan-acco…
fix(api/plans): stop leaking raw DB error in plan-fetch validation br…
sec(api): fix sibling PII leaks in plan/purchase handler paths (follo…
sec(api/plans): stop leaking raw account UUID + DB error in plan-acco…
fix(api/plans): stop leaking raw DB error in plan-fetch validation br…
sec(api): fix sibling PII leaks in plan/purchase handler paths (follo…
sec(api/plans): stop leaking raw account UUID + DB error in plan-acco…
fix(api/plans): stop leaking raw DB error in plan-fetch validation br…
sec(api): fix sibling PII leaks in plan/purchase handler paths (follo…
sec(api/plans): stop leaking raw account UUID + DB error in plan-acco…