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:

  1. 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.
  2. Filter out the API token somehow.
  3. Swallow the Guzzle exception and log something opaque instead.
  4. Try to talk some sense into the Guzzle maintainers regarding the logic of allowing the plain-text rendition of an Authorization header into an exception message 🤷🤷🤷

Remaining tasks

Decide which resolution to go with.

User interface changes

None

API changes

None

Data model changes

None

Command icon 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:

Comments

luke.leber created an issue. See original summary.

luke.leber’s picture

Issue summary: View changes
luke.leber’s picture

Issue summary: View changes
luke.leber’s picture

Issue summary: View changes
catch’s picture

Swallow the Guzzle exception and log something opaque instead.

That sounds like the easiest and most reliable option.

luke.leber’s picture

Issue summary: View changes

I've added another option, sort of like...

      $this->logger->error('%exception_type when making Cloudflare purge request with the following data: %data. Exception message: %exception_message', [
        '%exception_type' => $e::class,
        '%data' => json_encode($data),
        '%exception_message' => str_replace($api_token, '*****', $e->getMessage()),
      ]);

that could possibly work too.

luke.leber’s picture

I added a failing test case that should be ready for any fix.

1) Drupal\Tests\cloudflare_purger\Kernel\CloudflarePurgerTest::testNoTokenInLogMessages
Expectation failed for method name is "error" when invoked 1 time
Parameter 1 for invocation Psr\Log\LoggerInterface::error('%exception_type when making C...essage', [...]): void does not match expected value.
Failed asserting that Array &0 [
    '%exception_type' => 'Exception',
    '%data' => '{"tags":["auxn7f"]}',
    '%exception_message' => 'Your API token is "test". Uh oh...',
] is accepted by specified callback.
catch’s picture

Oh 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.

bkosborne’s picture

I 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.

luke.leber’s picture

Status: Active » Needs review

Switching 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.

bkosborne’s picture

Status: Needs review » Reviewed & tested by the community

  • catch committed b99900b6 on 1.0.x
    fix: #3607972 Plain text credentials can appear in logs
    
    By: luke.leber...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Yes this looks great. Committed/pushed to 1.0.x, thanks!

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.