Problem/Motivation
The presence of a newline character in the API token can cause credentials to leak into log messages.
Guzzle HTTP has a very unfortunate security posture when it comes to this type of flaw. They assume that all users of Guzzle should take precautions against sensitive credentials being included in log messages.
I've also reported this same type of flaw to the Google reCAPTCHA product security channel, but that was closed as a wontfix.
Steps to reproduce
Set up a key for the API token, but forget to check the "strip newline" checkbox on the key configuration.
2026-07-02T13:25:10Z [error] purger_cloudflare_8e22ab6ee0: InvalidArgumentException when making Cloudflare purge request with the following data: {"tags":["263x5c","1upqbl","1zter8","3e4xp0","esz1ba","138lkl","2plcon","1s2nrd","3reoen","138lkl","kvngvs","1k925f","sars05","kq8x9o","2plcon","bc0r1r","1ltqo4","14gv6h","25plgt","1s2nrd","1zuqs3","388od0","341le0","2tpqow","1ao6c8","1upqbl","263x5c"]}. Exception message: "Bearer <THE PLAIN TEXT TOKEN>
2026-07-02T13:25:10Z " is not valid header value.
😱😱😱😱😱
Proposed resolution
There are a few things that can be done here:
- Trim the API token before passing it into Guzzle and pray that a newline in a header is the only way to make a credential pop out in the logs.
- Filter out the API token somehow.
- Swallow the Guzzle exception and log something opaque instead.
- Try to talk some sense into the Guzzle maintainers regarding the logic of allowing the plain-text rendition of an
Authorizationheader into an exception message 🤷🤷🤷
Remaining tasks
Decide which resolution to go with.
User interface changes
None
API changes
None
Data model changes
None
Issue fork cloudflare_purger-3607972
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 3607972-plain-text-credentials
changes, plain diff MR !5
Comments
Comment #2
luke.leberComment #3
luke.leberComment #4
luke.leberComment #5
catchThat sounds like the easiest and most reliable option.
Comment #6
luke.leberI've added another option, sort of like...
that could possibly work too.
Comment #7
luke.leberI added a failing test case that should be ready for any fix.
Comment #8
catchOh I was wondering how we could strip the API token by parsing the message, then rejected it because that seemed unreliable if the message changed, but of course we know what the API token is because it's configured....
So yes that sounds great.
Comment #9
bkosborneI like this approach, nice thinking. I'd just recommend adding a comment above the str_replace that indicates the reasoning so we don't get confused about it in the future.
Comment #11
luke.leberSwitching over to NR; the test-only job fails (expected) and is fixed by the tweak to the purger.
As soon as I hear back from the Guzzle security folks (apparently they outsource that to Tide Lift now?), there might be another public issue opened to re-request a hardening that links to this specific use case.
Comment #12
bkosborneComment #14
catchYes this looks great. Committed/pushed to 1.0.x, thanks!