Skip to content

feat(aicore): clear AICORE_CLIENT_SECRET after token acquisition (AFSDK-4291) - #257

Draft
tiagoek wants to merge 1 commit into
feat/aicore-transparent-tlsfrom
feat/aicore-clear-client-secret
Draft

feat(aicore): clear AICORE_CLIENT_SECRET after token acquisition (AFSDK-4291)#257
tiagoek wants to merge 1 commit into
feat/aicore-transparent-tlsfrom
feat/aicore-clear-client-secret

Conversation

@tiagoek

@tiagoek tiagoek commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Disclaimer: Do not include SAP-internal or customer-specific information in this PR (e.g. internal system URLs, customer names, tenant IDs, or confidential configurations). This is a public repository.

Description

Stacked on #256 — merge that PR first, then retarget this one to main.

After the first successful litellm.completion() / litellm.acompletion() call, AICORE_CLIENT_SECRET is removed from os.environ. At that point LiteLLM has already captured the secret inside its token creator closure and no longer reads it from the environment. Removing it minimises the window of exposure to child processes and container introspection APIs.

Behaviour details

  • When: after the first call that returns without AuthenticationError
  • Idempotent: subsequent calls are no-ops once the secret is cleared
  • Rotation-safe: reload_aicore_credentials() (from feat(aicore): transparent TLS mode and reactive credential reload #256) resets the internal flag before re-calling set_aicore_config(), so the secret is written back temporarily and cleared again after the retry succeeds
  • Transparent TLS mode: no-op — in that mode set_aicore_config() never writes AICORE_CLIENT_SECRET to begin with
  • New public helper: reload_aicore_credentials() exported from the module

⚠️ Behavioural change for downstream consumers

Code that reads os.environ["AICORE_CLIENT_SECRET"] after calling completion() or acompletion() will receive a KeyError (or empty string via .get()). This pattern is an anti-pattern — the secret should only be consumed by the SDK, not by application code — but it exists in some downstream agents. Those agents will need to be updated to fetch credentials directly from the mounted secret volume rather than relying on the SDK's env var.

A scan of known downstream consumers identified two agents with confirmed breakage and several with patterns to review. This PR is kept as a draft to allow that migration to be coordinated before merge.

Related Issue

Type of Change

  • New feature (non-breaking change that adds functionality)
  • Bug fix
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Code refactoring
  • Dependency update

How to Test

python -m pytest tests/aicore/unit/ -v
# Expected: 73 passed

Manual verification:

  1. Call set_aicore_config() followed by a successful completion() call
  2. Assert os.environ.get("AICORE_CLIENT_SECRET") is None
  3. Make a second completion() call — verify it succeeds (LiteLLM uses its cached token)
  4. Simulate credential rotation: secret file updated, next call triggers AuthenticationError
  5. Verify completion() recovers: reloads credentials, clears secret again after retry

Checklist

  • I have read the Contributing Guidelines
  • I have verified that my changes solve the issue
  • I have added/updated automated tests to cover my changes
  • All tests pass locally
  • I have verified that my code follows the Code Guidelines
  • I have added type hints for all public APIs
  • My code does not contain sensitive information (credentials, tokens, etc.)
  • I have followed Conventional Commits for commit messages

Breaking Changes

AICORE_CLIENT_SECRET is removed from os.environ after the first successful completion call.

Affected pattern:

set_aicore_config()
completion(...)          # secret cleared here
secret = os.environ["AICORE_CLIENT_SECRET"]  # KeyError

Migration path: read credentials directly from the mounted volume (/etc/secrets/appfnd/aicore/<instance>/clientsecret) rather than from os.environ. Application code should not depend on the SDK's credential env vars — they are an implementation detail of the LiteLLM integration.

Additional Notes

This is the second in a series of two stacked PRs addressing credential exposure in the aicore module:

  1. feat(aicore): transparent TLS mode and reactive credential reload #256 — transparent TLS mode + reactive reload on AuthenticationError
  2. This PR — clear CLIENT_SECRET from env after token acquisition

When #256 is merged to main, this PR should be retargeted from feat/aicore-transparent-tls to main before merging.

… acquisition

After the first successful litellm.completion() call, AICORE_CLIENT_SECRET is
removed from os.environ. LiteLLM has captured the secret inside its token
creator closure at that point and no longer reads from the environment. Removing
it minimises the exposure window to child processes and container introspection
APIs (AFSDK-4291 / HASI2026203 SEC-309).

The flag is reset when credentials are reloaded (credential rotation flow) so
the secret is cleared again after the retry succeeds. No-op in transparent TLS
mode where the secret was never written.

Relates-to: AFSDK-4291
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.

1 participant