Filter API keys from LLM logs
What does this MR do and why?
Expanded AI logging can write self-hosted model credentials from model_metadata.api_key into llm.log. Filter structured api_key fields recursively when the LLM logger serializes an entry, replacing their values with [FILTERED] while preserving diagnostic context.
Filtering does not mutate the original payload, so outgoing requests retain their authentication credentials. The regression specs cover all four log levels, the instance/feature flag/namespace expanded logging switches, AI Gateway Client normal and streaming requests, and Duo Chat StepExecutor requests.
Two existing legacy logger fields exercised by the new specs are registered in the Labkit logging baseline. This change filters structured fields; it does not parse credentials embedded in arbitrary text.
References
Closes https://gitlab.com/gitlab-org/gitlab/-/issues/629564
The issue is labeled security-fix-in-public, and the maintainer confirmed that this fix can be contributed to the canonical repository: https://gitlab.com/gitlab-org/gitlab/-/work_items/629564#note_3882735325
How to set up and validate locally
Run:
bundle exec rspec ee/spec/lib/gitlab/llm/logger_spec.rb ee/spec/lib/gitlab/llm/ai_gateway/client_spec.rb ee/spec/lib/gitlab/duo/chat/step_executor_spec.rbLocal validation of this commit:
- 132 examples, 0 failures; exit status 0.
- Regression check with the new serialization method removed only in the test process: 15 examples, 13 expected failures exposing the synthetic API key.
- RuboCop: four Ruby files, no offenses.
- Gitleaks: final commit scanned, no leaks.
The request-path specs verify both redacted log output and unchanged outgoing request credentials.
MR acceptance checklist
Reviewed against the MR acceptance checklist. Independent local code review completed without blocking findings. CI and upstream review remain pending.