Our logging middleware redacted card data before writing to the error log. Simple rule: if a field name matches /card.?number|pan|cvv/i, replace the value with asterisks. Worked in every test we wrote.
Then a PCI scope review ran a raw grep across 90 days of log archives looking for 16-digit sequences. It found roughly 40,000 hits. All from one provider integration where the payment method came back nested as paymentMethod.details.number instead of card_number. The regex matched on field name, not on value shape, so a field called "number" three levels deep sailed right through.
The logs were only ever hit on 5xx responses from that provider, which happened about 60 times a day. Three weeks of that is enough volume to turn a monitoring bug into a real disclosure event, because now every one of those log lines has to be treated as a PAN exposure regardless of whether anyone actually read it.
Fix ended up being two masks stacked: field-name matching for known keys, plus a Luhn-check pass on any string value regardless of key, right before the log line gets serialized. Costs a bit of CPU on every log call. Cheaper than what came before it.
Anyone masking by field name only, or have you moved to value-shape detection as the primary check?
Top comments (0)