From db428154a4d41c33ae1fd92f7c668989ea29e8e7 Mon Sep 17 00:00:00 2001 From: mscherer Date: Fri, 1 May 2026 14:23:22 +0200 Subject: [PATCH] Document LoggedQuery::setRedactor() Adds a "Redacting Sensitive Values from Query Logs" subsection under the existing Query Logging section in `orm/database-basics.md` and a matching entry in the 5.4 migration guide's Database changes. Covers what the hook is for (any secret bound as a parameter ends up in every surface that consumes a LoggedQuery), how to register one, which exit points it covers (`interpolate()`, `getContext()`, `jsonSerialize()`), and the silent-fallback behaviour for redactors that throw or return a malformed value. --- docs/en/appendices/5-4-migration-guide.md | 5 +++ docs/en/orm/database-basics.md | 37 +++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/docs/en/appendices/5-4-migration-guide.md b/docs/en/appendices/5-4-migration-guide.md index a7440c2660..51266eb4e6 100644 --- a/docs/en/appendices/5-4-migration-guide.md +++ b/docs/en/appendices/5-4-migration-guide.md @@ -126,6 +126,11 @@ version is reported as `unknown`), the header is omitted. provides constants (`Index::GIN`, `Index::GIST`, `Index::SPGIST`, `Index::BRIN`, `Index::HASH`) for these access methods. See [Reading Indexes and Constraints](../orm/schema-system#reading-indexes-and-constraints). +- Added `LoggedQuery::setRedactor()` to scrub sensitive values from query + logs. Applies to `__toString()`, `getContext()`, and `jsonSerialize()`, + so file logs, structured loggers, and anything that JSON-encodes a + `LoggedQuery` all see the redacted shape. + See [Redacting Sensitive Values from Query Logs](../orm/database-basics#redacting-sensitive-values-from-query-logs). ### Http diff --git a/docs/en/orm/database-basics.md b/docs/en/orm/database-basics.md index 1914ffb337..deb4e05550 100644 --- a/docs/en/orm/database-basics.md +++ b/docs/en/orm/database-basics.md @@ -1232,6 +1232,43 @@ Log::setConfig('queries', [ > never leave query logging on in production as it will negatively impact the > performance of your application. +### Redacting Sensitive Values from Query Logs + +Query log lines render the executed SQL with bound parameters spliced +back in, so any secret bound as a parameter (encryption keys, +passwords, OAuth tokens) ends up in every surface that consumes a +`LoggedQuery` — file logs via `__toString()`, structured loggers via +`getContext()`, and anything that re-serialises the LoggedQuery as JSON +via `jsonSerialize()`. + +`Cake\Database\Log\LoggedQuery::setRedactor()` registers a global +`Closure` invoked before any of those exit points are exposed. The +closure receives the raw query string and bound params and must return +a 2-element array `[string $query, array $params]` with sensitive +values replaced: + +```php +use Cake\Database\Log\LoggedQuery; + +// In Application::bootstrap() or equivalent. +LoggedQuery::setRedactor(function (string $query, array $params): array { + foreach ($params as $key => $value) { + if (in_array($key, ['password', 'token', 'apiKey'], true)) { + $params[$key] = '«REDACTED»'; + } + } + return [$query, $params]; +}); +``` + +The hook fires in `interpolate()`, `getContext()`, and `jsonSerialize()`, +so every public exit path is covered. Pass `null` to clear a previously +registered redactor. + +A redactor that throws or returns a malformed value is silently ignored +for that call — the raw query and params are used as a safe fallback so +a faulty redactor cannot break logging. + ## Identifier Quoting By default, CakePHP does **not** quote identifiers in generated SQL queries. The