Description
CRITICAL: NVIDIA API Key Exposed in Process Arguments and Terminal Output
| Field |
Value |
| Severity |
Critical |
| CWE |
CWE-214 (Invocation of Process Using Visible Sensitive Information) |
| Files |
6 files, 8+ locations |
| Status |
Active |
Description
The NVIDIA_API_KEY is passed as a command-line argument to child processes in multiple scripts and JavaScript files. On Linux/macOS, command-line arguments are visible to any local user via ps aux or /proc/<pid>/cmdline. In one case, the raw key is also echoed to the terminal in cleartext.
This affects the production CLI tool, the setup scripts, the onboarding flow, and the E2E test harness.
Affected Locations
1. Key echoed to terminal in cleartext (WORST)
File: scripts/walkthrough.sh:72
echo " export NVIDIA_API_KEY=$NVIDIA_API_KEY"
When tmux is not available, the script prints the full API key value to stdout as part of suggested commands. This value will appear in:
- Terminal scrollback buffers
- Terminal session recordings
- CI/CD logs if run in automation
- Screen sharing / screenshots
2. Key embedded in tmux command string
File: scripts/walkthrough.sh:88
tmux split-window -h -t "$SESSION" \
"openshell sandbox connect nemoclaw -- bash -c 'export NVIDIA_API_KEY=$NVIDIA_API_KEY && nemoclaw-start openclaw agent --agent main --local --session-id live'"
The API key is embedded in the tmux command, visible via:
tmux list-windows -F '#{pane_start_command}'
ps aux during command startup
3. Key as openshell credential argument
File: scripts/setup.sh:122-126
upsert_provider \
"nvidia-nim" \
"openai" \
"NVIDIA_API_KEY=$NVIDIA_API_KEY" \ # ← passed as CLI argument
"OPENAI_BASE_URL=https://integrate.api.nvidia.com/v1"
The upsert_provider function passes credentials as arguments to openshell provider create --credential, making them visible in the process table.
4. Key as sandbox environment argument
File: scripts/setup.sh:182-184
openshell sandbox create --from "$BUILD_CTX/Dockerfile" --name "$SANDBOX_NAME" \
--provider nvidia-nim \
-- env NVIDIA_API_KEY="$NVIDIA_API_KEY" > "$CREATE_LOG" 2>&1
The key is passed as a CLI argument to openshell sandbox create. Note: the script is aware of this risk — line 189 filters the log output to avoid displaying it:
# Show progress lines (filter apt noise and env var dumps that contain NVIDIA_API_KEY)
5. Key in sudo command string
File: bin/nemoclaw.js:91
run(`sudo -E NVIDIA_API_KEY="${process.env.NVIDIA_API_KEY}" bash "${SCRIPTS}/setup-spark.sh"`);
The key is visible in the sudo command line. Both the parent process and the child bash process expose the key in /proc/*/cmdline.
6. Key as openshell provider credential (JavaScript)
File: bin/lib/onboard.js:729-734
run(
`openshell provider create --name nvidia-nim --type openai ` +
`--credential "NVIDIA_API_KEY=${process.env.NVIDIA_API_KEY}" ` +
`--config "OPENAI_BASE_URL=https://integrate.api.nvidia.com/v1" 2>&1 || true`,
{ ignoreError: true }
);
Same issue as setup.sh — credential passed as CLI argument to openshell.
7. Key as sandbox env argument (JavaScript)
File: bin/lib/onboard.js:468-470
if (process.env.NVIDIA_API_KEY) {
envArgs.push(`NVIDIA_API_KEY=${process.env.NVIDIA_API_KEY}`);
}
These envArgs are later passed as -- env KEY=VALUE CLI arguments to openshell sandbox create.
8. Key in curl Authorization header (test)
File: test/e2e/test-full-e2e.sh:229
-H "Authorization: Bearer $NVIDIA_API_KEY" \
The API key appears as a curl command-line argument, visible in the process table during the HTTP request.
9. Key in SSH command string (telegram bridge)
File: scripts/telegram-bridge.js:102
const cmd = `export NVIDIA_API_KEY='${API_KEY}' && nemoclaw-start openclaw agent --agent main --local -m '${escaped}' --session-id 'tg-${sessionId}'`;
The key is embedded in the SSH command string passed to spawn("ssh", [..., cmd]), visible in the process table. See separate report adv_shell_telegram_bridge.md for full analysis.
Impact
Any user on the same machine can harvest API keys by monitoring process arguments:
# Attacker's one-liner to harvest API keys from process arguments:
while true; do
ps aux | grep -oP 'NVIDIA_API_KEY=\K[^ "]+' >> /tmp/harvested_keys.txt
sleep 0.1
done
This is especially concerning in:
- Shared development machines — multiple developers on the same box
- CI/CD runners — shared runners process multiple tenants
- Brev/cloud VMs — the
deploy() function sends credentials to cloud instances
Recommended Fixes
For shell scripts (walkthrough.sh, setup.sh)
Echo fix (walkthrough.sh:72): Don't expand the variable — reference it instead:
# Before (leaks the key):
echo " export NVIDIA_API_KEY=$NVIDIA_API_KEY"
# After (safe — tells user to use their existing env var):
echo " export NVIDIA_API_KEY=\$NVIDIA_API_KEY"
Tmux fix (walkthrough.sh:88): Use tmux send-keys to type the export into the pane:
tmux split-window -h -t "$SESSION" "openshell sandbox connect nemoclaw"
tmux send-keys -t "$SESSION".1 "export NVIDIA_API_KEY=$NVIDIA_API_KEY && nemoclaw-start openclaw agent --agent main --local --session-id live" Enter
openshell credential fix (setup.sh, onboard.js): Check if openshell provider create supports --credential-stdin or --credential-file. If not, pass via environment variable:
# Before:
openshell provider create --credential "NVIDIA_API_KEY=$NVIDIA_API_KEY"
# After (if openshell supports env passthrough):
NVIDIA_API_KEY="$NVIDIA_API_KEY" openshell provider create --credential-env NVIDIA_API_KEY
For JavaScript (nemoclaw.js, onboard.js)
Use the env option of spawnSync/execSync:
// Before (key in CLI args):
run(`sudo -E NVIDIA_API_KEY="${process.env.NVIDIA_API_KEY}" bash "${SCRIPTS}/setup-spark.sh"`);
// After (key passed via process environment, not visible in ps):
run(`sudo -E bash "${SCRIPTS}/setup-spark.sh"`, {
env: { ...process.env, NVIDIA_API_KEY: process.env.NVIDIA_API_KEY }
});
For curl (test-full-e2e.sh)
Use a netrc file or config file:
# Before:
curl -H "Authorization: Bearer $NVIDIA_API_KEY" ...
# After:
curl --config <(echo "-H \"Authorization: Bearer $NVIDIA_API_KEY\"") ...
Or use -H @- with stdin if supported by the curl version.
Risk Assessment
- Impact: Credential theft by any local user on shared systems
- Exploitability: Trivial — single
ps aux | grep command
- Blast radius: NVIDIA API key provides access to inference endpoints at
integrate.api.nvidia.com and inference-api.nvidia.com, potentially incurring costs on the victim's account
- Mitigating factors: On single-user developer machines, the only user who can read process args is the same user who owns the key. The risk is primarily on shared/CI systems.
Reproduction Steps
Environment
Debug Output
Logs
Checklist
Description
CRITICAL: NVIDIA API Key Exposed in Process Arguments and Terminal Output
Description
The
NVIDIA_API_KEYis passed as a command-line argument to child processes in multiple scripts and JavaScript files. On Linux/macOS, command-line arguments are visible to any local user viaps auxor/proc/<pid>/cmdline. In one case, the raw key is also echoed to the terminal in cleartext.This affects the production CLI tool, the setup scripts, the onboarding flow, and the E2E test harness.
Affected Locations
1. Key echoed to terminal in cleartext (WORST)
File:
scripts/walkthrough.sh:72When
tmuxis not available, the script prints the full API key value to stdout as part of suggested commands. This value will appear in:2. Key embedded in tmux command string
File:
scripts/walkthrough.sh:88The API key is embedded in the tmux command, visible via:
tmux list-windows -F '#{pane_start_command}'ps auxduring command startup3. Key as openshell credential argument
File:
scripts/setup.sh:122-126The
upsert_providerfunction passes credentials as arguments toopenshell provider create --credential, making them visible in the process table.4. Key as sandbox environment argument
File:
scripts/setup.sh:182-184The key is passed as a CLI argument to
openshell sandbox create. Note: the script is aware of this risk — line 189 filters the log output to avoid displaying it:# Show progress lines (filter apt noise and env var dumps that contain NVIDIA_API_KEY)5. Key in sudo command string
File:
bin/nemoclaw.js:91The key is visible in the
sudocommand line. Both the parent process and the childbashprocess expose the key in/proc/*/cmdline.6. Key as openshell provider credential (JavaScript)
File:
bin/lib/onboard.js:729-734Same issue as setup.sh — credential passed as CLI argument to
openshell.7. Key as sandbox env argument (JavaScript)
File:
bin/lib/onboard.js:468-470These
envArgsare later passed as-- env KEY=VALUECLI arguments toopenshell sandbox create.8. Key in curl Authorization header (test)
File:
test/e2e/test-full-e2e.sh:229-H "Authorization: Bearer $NVIDIA_API_KEY" \The API key appears as a
curlcommand-line argument, visible in the process table during the HTTP request.9. Key in SSH command string (telegram bridge)
File:
scripts/telegram-bridge.js:102The key is embedded in the SSH command string passed to
spawn("ssh", [..., cmd]), visible in the process table. See separate reportadv_shell_telegram_bridge.mdfor full analysis.Impact
Any user on the same machine can harvest API keys by monitoring process arguments:
This is especially concerning in:
deploy()function sends credentials to cloud instancesRecommended Fixes
For shell scripts (
walkthrough.sh,setup.sh)Echo fix (walkthrough.sh:72): Don't expand the variable — reference it instead:
Tmux fix (walkthrough.sh:88): Use
tmux send-keysto type the export into the pane:openshell credential fix (setup.sh, onboard.js): Check if
openshell provider createsupports--credential-stdinor--credential-file. If not, pass via environment variable:For JavaScript (
nemoclaw.js,onboard.js)Use the
envoption ofspawnSync/execSync:For curl (test-full-e2e.sh)
Use a netrc file or config file:
Or use
-H @-with stdin if supported by the curl version.Risk Assessment
ps aux | grepcommandintegrate.api.nvidia.comandinference-api.nvidia.com, potentially incurring costs on the victim's accountReproduction Steps
Environment
Debug Output
Logs
Checklist