openclaw - ✅(Solved) Fix [Bug]: secrets audit PLAINTEXT_FOUND for synthetic codex-app-server apiKey in models.json [2 pull requests]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

openclaw secrets audit flags the codex provider's apiKey field in every agent's models.json as PLAINTEXT_FOUND. The flagged value is "codex-app-server" — a synthetic auth marker hardcoded by the codex extension, not a real API key.

Error Message

Document as accepted baseline exception. The 7 findings are excluded from security posture metrics via operational documentation.

Root Cause

Replacing the value with a SecretRef does not work because:

  • buildCodexProviderCatalog() overwrites models.json on each session start, reverting any SecretRef
  • The secrets audit reports SecretRef objects in models.json as REF_UNRESOLVED, recommending regeneration

Fix Action

Fix / Workaround

The secrets audit should not report known synthetic provider auth markers as plaintext secret findings. Either:

  • Exclude "codex-app-server" from PLAINTEXT_FOUND results
  • Downgrade to INFO with wording like "synthetic non-secret auth marker"
  • Add a secrets.audit.excludePatterns config option for operators to suppress known false positives

Current Workaround

PR fix notes

PR #69555: fix(codex): declare codex-app-server as nonSecretAuthMarker to silence audit FP

Description (problem / solution / changelog)

Problem

`openclaw secrets audit` flags `providers.codex.apiKey = "codex-app-server"` in every agent's `models.json` as `PLAINTEXT_FOUND`. The value is a synthetic auth marker the codex extension writes via `resolveSyntheticAuth`, not a real API key. Reporter @joerod26 in #69511 showed it inflating the plaintext count by 7 entries on a single install, obscuring real findings.

The audit already supports filtering known markers: `isNonSecretApiKeyMarker()` in `src/agents/model-auth-markers.ts` reads `plugin.nonSecretAuthMarkers` from every bundled plugin's manifest. `anthropic-vertex`, `minimax`, `lmstudio`, `ollama` already use this pattern for `gcp-vertex-credentials`, `minimax-oauth`, `lmstudio-local`, `ollama-local` respectively.

Codex was the only bundled plugin emitting a synthetic marker without declaring it — so the audit couldn't distinguish it from a real plaintext key.

Fix

Add `"nonSecretAuthMarkers": ["codex-app-server"]` to `extensions/codex/openclaw.plugin.json`.

No source/runtime change — the audit code path and the shared `isNonSecretApiKeyMarker` helper already handle this field correctly. This PR only fills the missing manifest declaration.

Pre-implement audit

  • A (existing helper): `isNonSecretApiKeyMarker` already reads `plugin.nonSecretAuthMarkers` from the manifest registry. Reusing. ✓
  • B (shared callers): The helper is called from `secrets/audit.ts:412`, `infra/provider-usage.auth.ts:79+85`, and `plugin-sdk/provider-auth.ts`. Adding a marker strictly extends the "not-a-secret" set — contract preserved, no caller behavior change. ✓
  • C (broader rival): Zero rivals for #69511. ✓

Testing

Added `src/secrets/audit.test.ts` regression — writes a codex provider block with `apiKey: "codex-app-server"` and asserts no `PLAINTEXT_FOUND` finding on `providers.codex.apiKey`.

Fixes #69511

Changed files

  • extensions/codex/openclaw.plugin.json (modified, +1/-0)
  • src/secrets/audit.test.ts (modified, +28/-0)

PR #69581: fix(codex): exclude codex-app-server synthetic apiKey from secrets audit

Description (problem / solution / changelog)

Summary

  • Problem: The secrets audit flags Codex's synthetic apiKey: "codex-app-server" (defined in extensions/codex/provider.ts) as PLAINTEXT_FOUND, even though it's not a real secret — Codex's real authentication lives inside the app-server transport.
  • Why it matters: Every user who has configured the Codex harness sees a false-positive plaintext finding in openclaw secrets audit, eroding trust in the signal.
  • What changed: Declared codex-app-server as a plugin-owned non-secret marker in extensions/codex/openclaw.plugin.json, and extended the existing model-auth-markers unit tests to lock in the behavior. No code changes — just the manifest and a regression test.
  • What did NOT change: Audit logic, isNonSecretApiKeyMarker implementation, any other plugin's manifest. The fix flows through the same path already used by ollama-local, lmstudio-local, gcp-vertex-credentials, and minimax-oauth.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #69511
  • This PR fixes a bug or regression

Root Cause

  • Root cause: The Codex extension was added without its synthetic codex-app-server apiKey being declared as a non-secret marker on the plugin manifest, while sibling plugins (Ollama, LMStudio, Anthropic-Vertex, Minimax) already do so.
  • Missing detection / guardrail: No explicit assertion that every bundled plugin which uses a synthetic apiKey value in models.json registers it through nonSecretAuthMarkers. (Out of scope for this PR, but could be a follow-up guardrail.)
  • Contributing context: The audit code path (src/secrets/audit.ts:412) already guards plaintext reporting with !isNonSecretApiKeyMarker(apiKey), which in turn calls listKnownNonSecretApiKeyMarkers() — a function that aggregates markers from the plugin manifest registry via loadPluginManifestRegistry({ cache: true }).plugins.flatMap(p => p.nonSecretAuthMarkers). Adding the marker to the Codex manifest is sufficient.

Regression Test Plan

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/agents/model-auth-markers.test.ts
  • Scenario the test should lock in:
    1. isNonSecretApiKeyMarker("codex-app-server") returns true.
    2. listKnownNonSecretApiKeyMarkers() includes "codex-app-server" after the manifest registry is loaded.
  • Why this is the smallest reliable guardrail: the two assertions exercise both the fast-path (direct marker check) and the manifest-driven aggregation, which is exactly how the audit and the merge/auth-store flows consume it. Any future accidental removal of the marker from the Codex manifest — or a regression in the manifest registry loader that drops bundled plugin markers — fails this test.
  • Existing test that already covers this (if any): src/agents/model-auth-markers.test.ts already covers the four peer markers (ollama-local, lmstudio-local, gcp-vertex-credentials, minimax-oauth). This PR extends those same tests with the Codex case.

User-visible / Behavior Changes

  • openclaw secrets audit no longer reports PLAINTEXT_FOUND for Codex's synthetic providers.codex.apiKey value in models.json.
  • No other user-visible changes. No new configuration options. No default changes.

Diagram

N/A — no flow change, only an additional entry in an existing allow-list loaded at plugin-registry init time.

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? Nocodex-app-server is a synthetic literal that has always been hardcoded in extensions/codex/provider.ts; this PR just declares it as a known non-secret marker. No tokens are read, stored, or transmitted differently.
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: macOS 26.5 (Apple Silicon, also applies to Linux)
  • Runtime/container: local
  • Model/provider: Codex harness (extensions/codex)
  • Integration/channel: openclaw secrets audit CLI
  • Relevant config: models.json containing providers.codex.apiKey = "codex-app-server" (the default after Codex discovery)

Steps

  1. Configure Codex provider (e.g. install the Codex extension and run a Codex-managed model once so models.json persists the provider).
  2. Run openclaw secrets audit.
  3. Observe finding: code: PLAINTEXT_FOUND, jsonPath: providers.codex.apiKey.

Expected

  • No PLAINTEXT_FOUND entry for the Codex provider, because codex-app-server is a synthetic non-secret marker.

Actual (before this PR)

  • The audit reports the synthetic value as a plaintext leak.

After this PR

  • Audit no longer reports it, matching the existing behavior for ollama-local, lmstudio-local, gcp-vertex-credentials, and minimax-oauth.

Evidence

  • Failing test/log before + passing after
    • The new assertions in src/agents/model-auth-markers.test.ts fail on main (with arrayContaining([…, "codex-app-server", …]) missing) and pass with this PR applied.
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios:
    • Inspected src/secrets/audit.ts to confirm the plaintext guard already calls isNonSecretApiKeyMarker.
    • Inspected src/agents/model-auth-markers.ts to confirm listKnownNonSecretApiKeyMarkers() aggregates bundled plugin manifests.
    • Confirmed the Codex plugin manifest is loaded via loadPluginManifestRegistry (checked src/plugins/manifest-registry.ts).
    • Confirmed codex-app-server is used as the synthetic value in extensions/codex/provider.ts (lines 88, 89, 117).
    • Confirmed JSON syntax of the updated manifest (python3 -c "import json; json.load(...)").
    • Confirmed the new assertions are placed next to peer markers so future regressions are obvious.
  • Edge cases checked: the manifest registry cache (cache: true) is loaded at startup; no code path reads nonSecretAuthMarkers outside the registry aggregation, so no additional sites need updating.
  • What I did not verify: did not run the full pnpm test:unit locally (no pnpm install on this machine); CI will run the suite.

Review Conversations

  • I will reply to or resolve every bot review conversation I address in this PR.
  • I will leave unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

  • Risk: a future plugin reuses the string codex-app-server in a non-Codex context and ends up whitelisted.
    • Mitigation: the string is intentionally Codex-branded and lives in the Codex plugin manifest. The registry aggregates from origin === "bundled" plugins only, so third-party plugins cannot injection-whitelist additional markers.

Changed files

  • extensions/codex/openclaw.plugin.json (modified, +1/-0)
  • src/agents/model-auth-markers.test.ts (modified, +2/-0)

Code Example

Secrets audit: findings. plaintext=10, unresolved=0, shadowed=0, legacy=13.
- [PLAINTEXT_FOUND] agents/main/agent/models.json:providers.codex.apiKey models.json provider apiKey is stored as plaintext.
- [PLAINTEXT_FOUND] agents/nikola/agent/models.json:providers.codex.apiKey models.json provider apiKey is stored as plaintext.
(... repeated for every agent with a codex provider block — 7 total)

---

resolveSyntheticAuth: () => ({
  apiKey: "codex-app-server",
  source: "codex-app-server",
  mode: "token"
})
RAW_BUFFERClick to expand / collapse

Product / Version

OpenClaw 2026.4.15 (041266a) — stable channel

Summary

openclaw secrets audit flags the codex provider's apiKey field in every agent's models.json as PLAINTEXT_FOUND. The flagged value is "codex-app-server" — a synthetic auth marker hardcoded by the codex extension, not a real API key.

Expected Behavior

The secrets audit should not report known synthetic provider auth markers as plaintext secret findings. Either:

  • Exclude "codex-app-server" from PLAINTEXT_FOUND results
  • Downgrade to INFO with wording like "synthetic non-secret auth marker"
  • Add a secrets.audit.excludePatterns config option for operators to suppress known false positives

Actual Behavior

Secrets audit: findings. plaintext=10, unresolved=0, shadowed=0, legacy=13.
- [PLAINTEXT_FOUND] agents/main/agent/models.json:providers.codex.apiKey models.json provider apiKey is stored as plaintext.
- [PLAINTEXT_FOUND] agents/nikola/agent/models.json:providers.codex.apiKey models.json provider apiKey is stored as plaintext.
(... repeated for every agent with a codex provider block — 7 total)

Impact

  • Inflates the plaintext count by 7 findings per installation
  • Obscures genuine secret exposure findings
  • Makes the audit's plaintext count unreliable as a security metric
  • Operators cannot distinguish "10 real secrets" from "0 real + 10 synthetic" without manual investigation
  • After completing a full SecretRef migration (runtime config + auth profiles), the audit still reports plaintext=10 — 7 of which are this false positive

Reproduction

  1. Install OpenClaw 2026.4.15 with codex extension enabled
  2. Start the gateway — on first session, buildCodexProviderCatalog() writes the codex provider block to each agent's models.json
  3. Run openclaw secrets audit
  4. Observe PLAINTEXT_FOUND for providers.codex.apiKey in every agent that has had a session

Evidence

The codex extension registers with:

resolveSyntheticAuth: () => ({
  apiKey: "codex-app-server",
  source: "codex-app-server",
  mode: "token"
})

The value "codex-app-server" is:

  • A constant string, not a credential
  • Hardcoded in dist/extensions/codex/openclaw.plugin.json
  • Regenerated by buildCodexProviderCatalog() on every real session start
  • Not usable for authentication — the real auth goes through OAuth tokens in auth-profiles.json

Replacing the value with a SecretRef does not work because:

  • buildCodexProviderCatalog() overwrites models.json on each session start, reverting any SecretRef
  • The secrets audit reports SecretRef objects in models.json as REF_UNRESOLVED, recommending regeneration

Current Workaround

Document as accepted baseline exception. The 7 findings are excluded from security posture metrics via operational documentation.

Why Not Fixed in 2026.4.15

The 2026.4.15 changelog contains no changes to the secrets audit scanning logic, codex-app-server marker handling, or audit exclusion patterns.

Recommended Priority

MEDIUM — cosmetic for security-sensitive operators, no runtime impact.


Draft prepared for GitHub filing. Do not include real secret values.

extent analysis

TL;DR

The most likely fix is to add a configuration option to exclude known synthetic provider auth markers, such as "codex-app-server", from PLAINTEXT_FOUND results in the secrets audit.

Guidance

  • Review the openclaw secrets audit logic to determine how to exclude or downgrade findings for known synthetic auth markers.
  • Consider adding a secrets.audit.excludePatterns config option to allow operators to suppress known false positives.
  • Investigate modifying the buildCodexProviderCatalog() function to use a SecretRef or other secure storage for the apiKey field, rather than hardcoding the synthetic auth marker.
  • Verify that any changes do not introduce new security vulnerabilities or impact the accuracy of the secrets audit.

Example

No code snippet is provided, as the necessary changes are not clearly defined without further review of the OpenClaw codebase.

Notes

The current workaround of documenting the issue as an accepted baseline exception is not ideal, as it relies on operational documentation and may not be scalable or reliable. A more robust solution, such as adding a configuration option or modifying the buildCodexProviderCatalog() function, is recommended.

Recommendation

Apply a workaround by adding a secrets.audit.excludePatterns config option to exclude known synthetic provider auth markers, such as "codex-app-server", from PLAINTEXT_FOUND results. This will allow operators to suppress known false positives and improve the accuracy of the secrets audit.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: secrets audit PLAINTEXT_FOUND for synthetic codex-app-server apiKey in models.json [2 pull requests]