fix #95895: [Security]: GEMINI_API_KEY written as a plaintext literal in the generated systemd service unit#96149
fix #95895: [Security]: GEMINI_API_KEY written as a plaintext literal in the generated systemd service unit#96149mushuiyu886 wants to merge 2 commits into
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 6, 2026, 2:39 AM ET / 06:39 UTC. Summary PR surface: Source +17, Tests +47. Total +64 across 2 files. Reproducibility: yes. Source inspection on current main shows auth-profile env refs enter the install plan with inline value-source metadata, while systemd renders file-only value sources through the generated EnvironmentFile. Review metrics: 1 noteworthy metric.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review detailsBest possible solution: Land this narrowed PR after maintainer/security review accepts the Google/Gemini auth-profile EnvironmentFile policy and exact-head gates remain green. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection on current main shows auth-profile env refs enter the install plan with inline value-source metadata, while systemd renders file-only value sources through the generated EnvironmentFile. Is this the best way to solve the issue? Yes, if maintainers accept the narrow policy. The patch uses the existing service env value-source seam instead of scrubbing renderer output, and the obvious broader alternative is a maintainer policy choice rather than a mechanical fix. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 806397f0d92c. Label changesLabel justifications:
Evidence reviewedPR surface: Source +17, Tests +47. Total +64 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (3 earlier review cycles) |
|
merge risk |
80033c6 to
a04b1fa
Compare
a04b1fa to
fe75764
Compare
Summary
GEMINI_API_KEYis managed throughOPENCLAW_SERVICE_MANAGED_ENV_KEYSand delivered by the generated EnvironmentFile.What Problem This Solves
Current main already keeps Google/Gemini config SecretRefs out of inline systemd unit assignments by treating those config keys as managed service env keys. The remaining gap is auth-profile env refs: Google/Gemini auth-profile keys still used the default inline service env value source, so the generated systemd unit could render plaintext
Environment=GOOGLE_API_KEY=...orEnvironment=GEMINI_API_KEY=...assignments for those auth-profile credentials.The fix marks known Google/Gemini auth-profile env-ref keys as
environmentValueSources: "file". The existing systemd staging contract then writes those values to the generated owner-only EnvironmentFile and omits plaintext assignments from the unit file.User Impact
Users who install the gateway as a systemd service with Google/Gemini credentials supplied through auth-profile env refs no longer get those keys embedded in the generated unit file. The service still receives the credentials at runtime via the generated EnvironmentFile.
Environment=lines.Origin / follow-up
Fixes #95895.
This is an existing PR updated after syncing with current main. The current main branch already covers the config SecretRef managed-key portion; this update keeps that behavior and narrows the remaining fix to Google/Gemini auth-profile env refs.
Competition / linked PR analysis
Linked PRs #95908, #96059, and #96065 also target #95895. After syncing with main, #96065's config SecretRef managed-key behavior is already present on the base branch.
environmentValueSources: "file"contract that systemd staging already owns for generated EnvironmentFile values, and applies it only to the remaining auth-profile Google/Gemini env-ref gap.0600EnvironmentFile with OpenClaw's production systemd staging code, then checks both absence of inline plaintext and presence of file-backed runtime values.This PR keeps the current main config SecretRef result:
GEMINI_API_KEYremains represented inOPENCLAW_SERVICE_MANAGED_ENV_KEYSand is still delivered by the generated EnvironmentFile. It adds the missing auth-profile value-source metadata so Google/Gemini auth-profile keys also go through the generated EnvironmentFile instead of inline unitEnvironment=values.Real behavior proof
Environment=GEMINI_API_KEY=...orEnvironment=GOOGLE_API_KEY=...entries in the generated systemd unit, while still being delivered to the service. The proof also verifies that current main's config SecretRef managed-key behavior remains intact.buildGatewayInstallPlanandstageSystemdServicepaths with a temporary HOME/state dir. A fakesystemctlbinary returned success for the local availability gate; OpenClaw's production systemd staging code produced the unit file and EnvironmentFile.0600. The install plan keeps current main'sOPENCLAW_SERVICE_MANAGED_ENV_KEYS=GEMINI_API_KEYresult for the config SecretRef path, and marks bothGEMINI_API_KEYandGOOGLE_API_KEYasfileinenvironmentValueSources.Merge risk
environmentValueSourcesmetadata that systemd staging already uses for file-backed service env values.passEnv, durable.env, generated service env defaults, and systemd EnvironmentFile rendering is preserved.Review findings addressed
Environment=assignments into the existing generated0600EnvironmentFile path; current-head proof stages the unit and EnvironmentFile to show runtime delivery is preserved without inline plaintext.GEMINI_API_KEY,GEMINI_API_KEYS,GEMINI_API_KEY_0, andGOOGLE_API_KEY; a generic all-provider auth-profile service-env policy remains out of scope unless maintainers request that broader direction.src/commands/daemon-install-helpers.ts. The current diff only adds the remaining auth-profile value-source behavior plus its regression test.baseUrl; direct current-headrun-tsgo.mjscore and extensions test type checks pass locally.Regression Test Plan
src/commands/daemon-install-helpers.test.tsGEMINI_API_KEYfrom a config SecretRef andGOOGLE_API_KEYfrom an auth-profile env ref; both must keep their values in the plan and be markedenvironmentValueSources: "file", while current main'sOPENCLAW_SERVICE_MANAGED_ENV_KEYS=GEMINI_API_KEYbehavior remains intact.node scripts/run-vitest.mjs src/commands/daemon-install-helpers.test.ts./node_modules/.bin/oxfmt --check src/commands/daemon-install-helpers.ts src/commands/daemon-install-helpers.test.tsnode scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.core.json src/commands/daemon-install-helpers.ts src/commands/daemon-install-helpers.test.tsnode scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.core.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core-test-after-sync.tsbuildinfonode scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test-after-sync.tsbuildinfogit diff --checkPROOF_HEAD=$(git rev-parse HEAD) ./node_modules/.bin/tsx /media/vdb/code/ai/aispace/openclaw-issue-95895-evidence/gemini-managed-env-proof.mtsRisk / Compatibility
Risk is limited to Google/Gemini auth-profile env-ref service rendering. Other provider auth-profile env refs keep the existing inline behavior, and current-main config SecretRef managed-key behavior is unchanged.
passEnv, generated service env defaults, or renderer behavior outside these Google/Gemini env key names.buildGatewayInstallPlanis the source-of-truth contract for service env values and theirenvironmentValueSources; systemd staging already treatsfilesources as generated EnvironmentFile values.0600, and includes the synced target tests, formatting check, lint check, type-check shard, and whitespace check.The generated systemd service still receives the Google/Gemini values because the change uses the existing file-backed EnvironmentFile path rather than dropping the values from the plan.
What was not changed
passEnvhandling.Root Cause
Environment=assignments.file-backed routes them through the existing generated EnvironmentFile path, which removes plaintext unit assignments while preserving runtime delivery.