Skip to content

fix: redact credentials in llm connection and provider logs - #171

Draft
sjvans wants to merge 1 commit into
mainfrom
fix/redact-llm-credentials-in-logs
Draft

sjvans wants to merge 1 commit into
mainfrom
fix/redact-llm-credentials-in-logs

Conversation

@sjvans

@sjvans sjvans commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Problem

Two log statements print the resolved llm configuration, which carries secrets in its credentials (API keys, client secrets):

  • cds-plugin.js — LOG.info("cds.connect.to 'llm' with:", …) on served (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 credentials key-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, so apiKey / clientsecret are masked while non-secret fields (url, baseURL, destination, model, …) stay visible for debugging.

Known limitation (tracked separately)

redacted()'s key regex does not cover bearer token / access_token / Authorization. For the currently supported providers (anthropic/openai apiKey, AI Core clientsecret) this is sufficient, but a resolved bearer token in a credentials object would still pass through. Closing that gap centrally is proposed in a separate cds sketch PR.


🤖 Draft for review.

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.
@hyperspace-pr-bot

Copy link
Copy Markdown

Summary

The following content is AI-generated and provides a summary of the pull request:


Title

fix: Redact LLM credentials in connection and provider logs

Category

Bug Fix

Summary

This change prevents LLM credentials from being exposed in logs by routing resolved LLM configuration logging through the shared cds.utils.redacted() helper.

Changes

  • Replaced custom credential masking in cds-plugin.js with cds.utils.redacted() when logging cds.connect.to 'llm' configuration.
  • Replaced ad-hoc credential stripping in srv/handlers/index.js with cds.utils.redacted() when logging LLM provider creation options.
  • Added a changelog entry documenting that credentials are no longer exposed in LLM connection/provider logs.

Impact

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

  • Added relevant entry to the change log?

Related: #159


  • 🔄 Regenerate and Update Summary
  • ✏️ Insert as PR Description (deletes this comment)
  • 🗑️ Delete comment
PR Bot Information

Version: 1.31.65

  • Event Trigger: pull_request.opened
  • Output Template: Repository PR Template
  • GithubContextProvider: chore: Better system prompts #159
  • LLM: gpt-5.5
  • Correlation ID: 9ece9e50-bdd9-11f1-98b1-73e7d07e4943
  • File Content Strategy: Full file content
  • Summary Prompt: Default Prompt

Comment thread CHANGELOG.md

### 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()`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changelog entry is misleading. We do not redact more now, we just switch to cds.utils.redacted

Comment thread cds-plugin.js
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))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense. i'll take that as feedback for redacted. no need to proceed with this until then.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants