What was broken
RedactingFormatter in Monolog hides values under sensitive keys such as password. It does this in two ways: it replaces the key's value in the context with a mask, and then it sweeps the finished log text and removes the original secrets from it. The sweep catches copies that leaked through other paths, for example through PsrLogMessageProcessor, which interpolates context values into the message.
The sweep only works for secrets the formatter collected first, and the collecting method only accepted strings. When the value under password was an array, nothing from it made it onto the list of secrets. A call like:
ended with a correctly masked context and the password in plain text in the message, because the processor had JSON-encoded the array into the {password} placeholder.
What we changed
We added a small helper, collectSensitiveValue(), that walks the value under a sensitive key and collects every string it finds, however deeply nested. It respects the same MAX_DEPTH guard the class already uses for self-referencing structures.
How we tested it
A new test runs a record through PsrLogMessageProcessor and then through RedactingFormatter, and checks that the secret nested in the array does not appear in the output and that [REDACTED] does.
The result
The library's author merged the change on 9 September 2026. Logs from applications that pass arrays of form data to Monolog no longer give passwords away through the message text.