Conversation
The 'cds.connect.to llm' info log and the LLMProvider debug log both printed the resolved llm configuration, whose credentials object carries api keys / client secrets. Route both through cds.utils.redacted() so the shared masking applies instead of ad-hoc per-call-site handling.
SummaryThe following content is AI-generated and provides a summary of the pull request: Titlefix: Redact LLM credentials in connection and provider logs CategoryBug Fix SummaryThis change prevents LLM credentials from being exposed in logs by routing resolved LLM configuration logging through the shared Changes
ImpactSensitive fields such as API keys, client secrets, passwords, certificates, and similar credential values are now consistently masked in these log statements, while non-sensitive configuration remains visible for troubleshooting. Have you...
Related: #159
PR Bot InformationVersion:
|
|
|
||
| ### Fixed | ||
|
|
||
| - Credentials are no longer exposed in logs when connecting to the `llm` service or instantiating an LLM provider; both now redact via `cds.utils.redacted()` |
There was a problem hiding this comment.
The changelog entry is misleading. We do not redact more now, we just switch to cds.utils.redacted
| if (apiKey) credentials.apiKey = "***" | ||
| LOG.info(`cds.connect.to 'llm' with:`, { ...config, credentials }) | ||
| const config = cds.requires.llm | ||
| LOG.info(`cds.connect.to 'llm' with:`, cds.utils.redacted(config)) |
There was a problem hiding this comment.
The output is less helpful now...
Before:
[agents] - cds.connect.to 'llm' with: {
kind: 'anthropic',
model: 'claude-sonnet-4-6',
credentials: {
anthropicApiUrl: 'http://localhost:6655/anthropic/',
apiKey: '***'
}
}Now:
[agents] - cds.connect.to 'llm' with: {
kind: 'anthropic',
model: 'claude-sonnet-4-6',
credentials: { anthropicApiUrl: '...', apiKey: '...' }
}The url is usually something that I want to know
There was a problem hiding this comment.
makes sense. i'll take that as feedback for redacted. no need to proceed with this until then.
Problem
Two log statements print the resolved
llmconfiguration, which carries secrets in itscredentials(API keys, client secrets):cds-plugin.js—LOG.info("cds.connect.to 'llm' with:", …)onserved(INFO, always on)srv/handlers/index.js—LOG.debug("Creating LLMProvider instance …", …)Both guarded against the raw object only with ad-hoc, hand-maintained masking (a field whitelist in the plugin, a
credentialskey-strip in the handler). This is the concern raised in #159 (discussion r4141952091).Change
Route both through the shared
cds.utils.redacted()helper instead of per-call-site masking.redacted()deep-clones and masks values whose key matches/(passw)|(cert)|(ca)|(secret)|(key)/i, soapiKey/clientsecretare masked while non-secret fields (url,baseURL,destination,model, …) stay visible for debugging.Known limitation (tracked separately)
redacted()'s key regex does not cover bearertoken/access_token/Authorization. For the currently supported providers (anthropic/openaiapiKey, AI Coreclientsecret) this is sufficient, but a resolved bearer token in a credentials object would still pass through. Closing that gap centrally is proposed in a separatecdssketch PR.🤖 Draft for review.