fix(log): scrub PII + secret-adjacent data from auth + stripe log lines #280

Merged
YousifShkara merged 1 commit from fix/BUNYIP-265-log-hygiene into main 2026-06-30 06:36:59 +02:00
Owner

BUNYIP-265: tighten the log surface so PII and Stripe customer data stop ending up in long-retained log files. The 2026-06-30 audit named the load-bearing call sites.

  • bunyip-api/src/handlers/auth.rs:260,405,466,848,887: five tracing::error! sites emitted email = %email on email-send failure. The email failure mode is the actionable signal; the address is PII + an enumeration channel ("does this address have an account?" answered by checking the logs). Drop the email field; correlation already comes from the request_id middleware. Same fix at the "Initial admin user created via setup" tracing::info! (now logs user_id only).
  • bunyip-api/src/handlers/auth.rs:928-936 (auth_redirect): the debug log emitted target_url = %target_url, which on this code path carries OIDC state / code / return_to query parameters. Parse the URL once and log only the path; the query string never reaches log files.
  • crates/bunyip-domain/src/services/stripe.rs:948,1001: two tracing::error! sites emitted the FULL Stripe response body on failure. Stripe error envelopes commonly carry customer email, subscription id, last-4 PAN digits - none of which should sit in log files. New stripe_error_envelope helper parses the documented {"error":{"code":"...","type":"..."}} shape and the loggers emit only those two operationally-actionable fields.

EMAIL_LOG_TOKENS is already fail-closed in production (crates/bunyip-domain/src/config.rs:124 - let log_tokens = !is_production && ...), so the audit's separate concern about magic-link / reset URL leakage is already addressed and untouched here.

#BUNYIP-265

BUNYIP-265: tighten the log surface so PII and Stripe customer data stop ending up in long-retained log files. The 2026-06-30 audit named the load-bearing call sites. - `bunyip-api/src/handlers/auth.rs:260,405,466,848,887`: five `tracing::error!` sites emitted `email = %email` on email-send failure. The email failure mode is the actionable signal; the address is PII + an enumeration channel ("does this address have an account?" answered by checking the logs). Drop the email field; correlation already comes from the request_id middleware. Same fix at the "Initial admin user created via setup" `tracing::info!` (now logs `user_id` only). - `bunyip-api/src/handlers/auth.rs:928-936` (`auth_redirect`): the debug log emitted `target_url = %target_url`, which on this code path carries OIDC `state` / `code` / `return_to` query parameters. Parse the URL once and log only the path; the query string never reaches log files. - `crates/bunyip-domain/src/services/stripe.rs:948,1001`: two `tracing::error!` sites emitted the FULL Stripe response body on failure. Stripe error envelopes commonly carry customer email, subscription id, last-4 PAN digits - none of which should sit in log files. New `stripe_error_envelope` helper parses the documented `{"error":{"code":"...","type":"..."}}` shape and the loggers emit only those two operationally-actionable fields. `EMAIL_LOG_TOKENS` is already fail-closed in production (`crates/bunyip-domain/src/config.rs:124` - `let log_tokens = !is_production && ...`), so the audit's separate concern about magic-link / reset URL leakage is already addressed and untouched here. #BUNYIP-265
fix(log): scrub PII + secret-adjacent data from auth + stripe log lines
All checks were successful
Check / fmt + clippy + build + tests (pull_request) Successful in 11m19s
E2E / Playwright against deployment (pull_request) Successful in 58s
Create release / Create release from merged PR (pull_request) Has been skipped
171fa035bf
BUNYIP-265: tighten the log surface so PII and Stripe customer data stop ending up in long-retained log files. The 2026-06-30 audit named the load-bearing call sites.

- `bunyip-api/src/handlers/auth.rs:260,405,466,848,887`: five `tracing::error!` sites emitted `email = %email` on email-send failure. The email failure mode is the actionable signal; the address is PII + an enumeration channel ("does this address have an account?" answered by checking the logs). Drop the email field; correlation already comes from the request_id middleware. Same fix at the "Initial admin user created via setup" `tracing::info!` (now logs `user_id` only).
- `bunyip-api/src/handlers/auth.rs:928-936` (`auth_redirect`): the debug log emitted `target_url = %target_url`, which on this code path carries OIDC `state` / `code` / `return_to` query parameters. Parse the URL once and log only the path; the query string never reaches log files.
- `crates/bunyip-domain/src/services/stripe.rs:948,1001`: two `tracing::error!` sites emitted the FULL Stripe response body on failure. Stripe error envelopes commonly carry customer email, subscription id, last-4 PAN digits - none of which should sit in log files. New `stripe_error_envelope` helper parses the documented `{"error":{"code":"...","type":"..."}}` shape and the loggers emit only those two operationally-actionable fields.

`EMAIL_LOG_TOKENS` is already fail-closed in production (`crates/bunyip-domain/src/config.rs:124` - `let log_tokens = !is_production && ...`), so the audit's separate concern about magic-link / reset URL leakage is already addressed and untouched here.

#BUNYIP-265
YousifShkara deleted branch fix/BUNYIP-265-log-hygiene 2026-06-30 06:36:59 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/bunyip!280
No description provided.