fix(orchestrator): use provider-specific credential environment variable#191
fix(orchestrator): use provider-specific credential environment variable#191dumko2001 wants to merge 1 commit intoNVIDIA:mainfrom
Conversation
ericksoa
left a comment
There was a problem hiding this comment.
LGTM — correct fix for credential env var passthrough.
|
Hey @ericksoa , I've been contributing to the GWS CLI recently, and the developer there is using an OpenClaw bot and a separate Gemini bot to review pull requests and push PRs and thats accelerating the development of the project. I want to propose we use something like that here as a reviewer here for this repo. It would help us review PRs more easily and accelerate getting more commits in. Maybe we can have a bot that pushes PR's too .Since I'm already working on the GWS CLI and this repo, I'd like to help build this or even take charge of more responsibilities around the agent/reviewer side . Is this something we can explore for this repo? |
… in argv Fixes: NVIDIA#325 (API key exposed in process list via ps aux) Supersedes: PRs NVIDIA#191, NVIDIA#330 The root cause: all three execution layers passed the actual credential VALUE as --credential KEY=VALUE, making it visible to any local user via `ps aux` or /proc/<pid>/cmdline. Safe pattern: set the secret in the child's inherited env, then pass only the env-var NAME to --credential (openshell env-lookup form). nemoclaw/src/commands/onboard.ts - process.env[credentialEnv] = apiKey before execOpenShell - --credential arg: credentialEnv (name only, not KEY=VALUE) - applies to both provider create and provider update paths nemoclaw-blueprint/orchestrator/runner.py - Rename credential_env -> target_cred_env with type-based fallback (nvidia -> NVIDIA_API_KEY, openai -> OPENAI_API_KEY) when not set in the blueprint profile. Supersedes PR NVIDIA#191's partial fix. - os.environ[target_cred_env] = credential before run_cmd - --credential arg: target_cred_env (name only) nemoclaw-blueprint/blueprint.yaml - Add credential_env: NVIDIA_API_KEY to the default profile. Without this field the type-based fallback would silently use OPENAI_API_KEY for the nvidia provider_type, causing auth failure. nemoclaw/src/onboard/config.ts - writeFileSync for config.json now passes mode: 0o600 so the file containing endpoint/model/credentialEnv metadata is not world-readable. test/credential-exposure.test.js (new file) - Static source scan: asserts no --credential KEY=VALUE pattern in any of the 3 execution layer files (allowlists dummy/ollama stubs) - Layer-specific structural checks (process.env set, os.environ set, blueprint default profile has credential_env) - Runtime injection PoC: proves old bash -c IS vulnerable; new runCaptureArgv IS NOT All 84 tests pass.
… in argv Fixes: NVIDIA#325 (API key exposed in process list via ps aux) Supersedes: PRs NVIDIA#191, NVIDIA#330 The root cause: all three execution layers passed the actual credential VALUE as --credential KEY=VALUE, making it visible to any local user via `ps aux` or /proc/<pid>/cmdline. Safe pattern: set the secret in the child's inherited env, then pass only the env-var NAME to --credential (openshell env-lookup form). nemoclaw/src/commands/onboard.ts - process.env[credentialEnv] = apiKey before execOpenShell - --credential arg: credentialEnv (name only, not KEY=VALUE) - applies to both provider create and provider update paths nemoclaw-blueprint/orchestrator/runner.py - Rename credential_env -> target_cred_env with type-based fallback (nvidia -> NVIDIA_API_KEY, openai -> OPENAI_API_KEY) when not set in the blueprint profile. Supersedes PR NVIDIA#191's partial fix. - os.environ[target_cred_env] = credential before run_cmd - --credential arg: target_cred_env (name only) nemoclaw-blueprint/blueprint.yaml - Add credential_env: NVIDIA_API_KEY to the default profile. Without this field the type-based fallback would silently use OPENAI_API_KEY for the nvidia provider_type, causing auth failure. nemoclaw/src/onboard/config.ts - writeFileSync for config.json now passes mode: 0o600 so the file containing endpoint/model/credentialEnv metadata is not world-readable. test/credential-exposure.test.js (new file) - Static source scan: asserts no --credential KEY=VALUE pattern in any of the 3 execution layer files (allowlists dummy/ollama stubs) - Layer-specific structural checks (process.env set, os.environ set, blueprint default profile has credential_env) - Runtime injection PoC: proves old bash -c IS vulnerable; new runCaptureArgv IS NOT All 84 tests pass.
… in argv Fixes: NVIDIA#325 (API key exposed in process list via ps aux) Supersedes: PRs NVIDIA#191, NVIDIA#330 The root cause: all three execution layers passed the actual credential VALUE as --credential KEY=VALUE, making it visible to any local user via `ps aux` or /proc/<pid>/cmdline. Safe pattern: set the secret in the child's inherited env, then pass only the env-var NAME to --credential (openshell env-lookup form). nemoclaw/src/commands/onboard.ts - process.env[credentialEnv] = apiKey before execOpenShell - --credential arg: credentialEnv (name only, not KEY=VALUE) - applies to both provider create and provider update paths nemoclaw-blueprint/orchestrator/runner.py - Rename credential_env -> target_cred_env with type-based fallback (nvidia -> NVIDIA_API_KEY, openai -> OPENAI_API_KEY) when not set in the blueprint profile. Supersedes PR NVIDIA#191's partial fix. - os.environ[target_cred_env] = credential before run_cmd - --credential arg: target_cred_env (name only) nemoclaw-blueprint/blueprint.yaml - Add credential_env: NVIDIA_API_KEY to the default profile. Without this field the type-based fallback would silently use OPENAI_API_KEY for the nvidia provider_type, causing auth failure. nemoclaw/src/onboard/config.ts - writeFileSync for config.json now passes mode: 0o600 so the file containing endpoint/model/credentialEnv metadata is not world-readable. test/credential-exposure.test.js (new file) - Static source scan: asserts no --credential KEY=VALUE pattern in any of the 3 execution layer files (allowlists dummy/ollama stubs) - Layer-specific structural checks (process.env set, os.environ set, blueprint default profile has credential_env) - Runtime injection PoC: proves old bash -c IS vulnerable; new runCaptureArgv IS NOT All 84 tests pass.
During openshell provider create, the NVIDIA API key was interpolated directly into shell command strings, making it visible via ps aux, /proc/PID/cmdline, and process monitoring tools on shared systems. Fixes: - bin/lib/onboard.js: Write credential to temp file (mode 0600, exclusive create) and use $(cat ...) substitution so the key only exists in bash's memory during expansion, not in the parent's command string. File is cleaned up in a finally block. - scripts/setup.sh: Same temp file + cat pattern with trap EXIT cleanup. - bin/nemoclaw.js: Use sudo --preserve-env instead of interpolating the key into the command string. - nemoclaw/src/commands/onboard.ts: Added comment noting the remaining /proc exposure requires openshell --credential-file or --credential-from-env support (see PR NVIDIA#191). The credential still appears briefly in the openshell child process arguments. Full mitigation requires openshell to support reading credentials from a file or environment variable rather than CLI args. Fixes NVIDIA#325 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Hi @dumko2001 — using provider-specific credential env vars is cleaner and more correct. A rebase onto the latest main is needed before we can review though. Mind updating? Thanks for all the contributions! |
01bcad3 to
29ec306
Compare
📝 WalkthroughWalkthroughThe Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
nemoclaw-blueprint/orchestrator/runner.py (1)
192-199:⚠️ Potential issue | 🟠 MajorNormalize provider type before fallback credential-env selection.
Line 199 uses a case-sensitive check (
provider_type == "nvidia"). Mixed-case values (e.g.,NVIDIA) will incorrectly fall back toOPENAI_API_KEY, which can break auth at runtime.Proposed fix
- provider_type: str = inference_cfg.get("provider_type", "openai") + provider_type_raw = str(inference_cfg.get("provider_type", "openai")) + provider_type: str = provider_type_raw.strip().lower() @@ - if not target_cred_env: - target_cred_env = "NVIDIA_API_KEY" if provider_type == "nvidia" else "OPENAI_API_KEY" + if not target_cred_env: + target_cred_env = "NVIDIA_API_KEY" if provider_type == "nvidia" else "OPENAI_API_KEY"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@nemoclaw-blueprint/orchestrator/runner.py` around lines 192 - 199, The fallback credential selection uses a case-sensitive check on provider_type; update the logic so provider_type is normalized before comparison (e.g., call .lower() or .casefold() on the value returned from inference_cfg.get or when performing the comparison) so the target_cred_env assignment (the branch that sets "NVIDIA_API_KEY" vs "OPENAI_API_KEY") correctly handles mixed-case inputs; modify the code that assigns provider_type or the conditional that sets target_cred_env (referencing provider_type, target_cred_env, and inference_cfg) to use the normalized string for the comparison.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@nemoclaw-blueprint/orchestrator/runner.py`:
- Around line 192-199: The fallback credential selection uses a case-sensitive
check on provider_type; update the logic so provider_type is normalized before
comparison (e.g., call .lower() or .casefold() on the value returned from
inference_cfg.get or when performing the comparison) so the target_cred_env
assignment (the branch that sets "NVIDIA_API_KEY" vs "OPENAI_API_KEY") correctly
handles mixed-case inputs; modify the code that assigns provider_type or the
conditional that sets target_cred_env (referencing provider_type,
target_cred_env, and inference_cfg) to use the normalized string for the
comparison.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b9e10803-3cb8-44ed-bc3f-d2543a50fd96
📒 Files selected for processing (1)
nemoclaw-blueprint/orchestrator/runner.py
|
@cv rebased. |
During openshell provider create, the NVIDIA API key was interpolated directly into shell command strings, making it visible via ps aux, /proc/PID/cmdline, and process monitoring tools on shared systems. Fixes: - bin/lib/onboard.js: Write credential to temp file (mode 0600, exclusive create) and use $(cat ...) substitution so the key only exists in bash's memory during expansion, not in the parent's command string. File is cleaned up in a finally block. - scripts/setup.sh: Same temp file + cat pattern with trap EXIT cleanup. - bin/nemoclaw.js: Use sudo --preserve-env instead of interpolating the key into the command string. - nemoclaw/src/commands/onboard.ts: Added comment noting the remaining /proc exposure requires openshell --credential-file or --credential-from-env support (see PR NVIDIA#191). The credential still appears briefly in the openshell child process arguments. Full mitigation requires openshell to support reading credentials from a file or environment variable rather than CLI args. Fixes NVIDIA#325 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…d remove openclaw (NVIDIA#191)
|
We no longer have a |
Rationale
Using a hardcoded ENV variable for all providers prevented multi-provider configurations (e.g. NVIDIA and NIM) from coexisting cleanly.
Changes
Dynamically resolved the correct environment variable name based on the provider type in the orchestrator dispatch.
Verification Results
npm test.Summary by CodeRabbit