-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Bot Tokens (Discord, Slack, Telegram) Bypass OpenShell Credential Isolation - IssueFinder - SN 01 #1333
Description
Description
Discord, Slack, and Telegram bot tokens bypass the OpenShell provider system and are injected as plaintext environment variables directly into the sandbox container. The Telegram bridge also injects raw NVIDIA_API_KEY via SSH. This means any process inside the sandbox can read these credentials.
Impact
API key and bot token exposure to any process in the sandbox, including malicious npm packages and agent-triggered code.
Affected Area
- Module(s): onboard.js, telegram-bridge.js
- Service(s): Sandbox container, Telegram bridge
Notes
These issues are well-documented at #1109 and #1108. Our audit confirmed the code paths that expose these credentials. The recommended fix is to use the OpenShell provider system for all credentials rather than env var injection.
Exact Fix
File: bin/lib/onboard.js lines 2193-2200
Problem: Bot tokens are copied from host env into the sandbox env object without going through the OpenShell credential provider system.
Current code (lines 2193-2200):
const discordToken = getCredential("DISCORD_BOT_TOKEN") || process.env.DISCORD_BOT_TOKEN;
if (discordToken) {
sandboxEnv.DISCORD_BOT_TOKEN = discordToken;
}
const slackToken = getCredential("SLACK_BOT_TOKEN") || process.env.SLACK_BOT_TOKEN;
if (slackToken) {
sandboxEnv.SLACK_BOT_TOKEN = slackToken;
}Replace with:
// Do NOT inject bot tokens as env vars.
// Instead, store them via OpenShell credential provider:
// openshell credential set DISCORD_BOT_TOKEN <value>
// The gateway will inject them server-side at request time,
// preventing sandbox-side processes from reading the raw token.
const botTokenKeys = ["DISCORD_BOT_TOKEN", "SLACK_BOT_TOKEN", "TELEGRAM_BOT_TOKEN"];
for (const key of botTokenKeys) {
delete sandboxEnv[key]; // Ensure token is NOT in sandbox env
const token = getCredential(key) || process.env[key];
if (token) {
// Store via OpenShell provider for server-side injection
runOpenshell(["credential", "set", key, token]);
note(` ${key} stored via OpenShell provider (not exposed to sandbox).`);
}
}File: scripts/telegram-bridge.js line 112
Problem: NVIDIA_API_KEY passed directly in SSH command string.
Current code (line 112):
const cmd = `export NVIDIA_API_KEY=${shellQuote(API_KEY)} && nemoclaw-start openclaw agent ...`;Replace with:
// Pass API key via SSH stdin, not command string
const cmd = `read -r NVIDIA_API_KEY && export NVIDIA_API_KEY && nemoclaw-start openclaw agent --agent main --local -m ${shellQuote(message)} --session-id ${shellQuote("tg-" + safeSessionId)}`;
const proc = spawn("ssh", ["-T", "-F", confPath, `openshell-${SANDBOX}`, cmd], {
timeout: 120000,
stdio: ["pipe", "pipe", "pipe"], // Changed: stdin is now 'pipe'
});
proc.stdin.write(API_KEY + "\n");
proc.stdin.end();Related GitHub Issue Check
- Matching open issue: Discord, Slack, and Telegram bot tokens bypass OpenShell provider system — injected as plaintext env vars into sandbox #1109
- Matching open issue: Telegram bridge bypasses OpenShell credential isolation — raw NVIDIA_API_KEY injected into sandbox via SSH #1108
- Duplicate status: Confirmed existing
- Reasoning: Our audit found plaintext env var injection of bot tokens into sandbox. These issues are tracked at Discord, Slack, and Telegram bot tokens bypass OpenShell provider system — injected as plaintext env vars into sandbox #1109 (Discord/Slack/Telegram tokens) and Telegram bridge bypasses OpenShell credential isolation — raw NVIDIA_API_KEY injected into sandbox via SSH #1108 (Telegram bridge NVIDIA_API_KEY injection).
Reproduction Steps
- Configure a Discord bot token during onboard:
nemoclaw onboard # Enter Discord bot token when prompted - After sandbox creation, exec into the sandbox and check environment:
openshell sandbox exec <sandbox-name> -- env | grep -i 'DISCORD\|SLACK\|TOKEN'
- Observe:
DISCORD_BOT_TOKENandSLACK_BOT_TOKENare visible as environment variables inside the sandbox - Compare:
NVIDIA_API_KEYis correctly removed from sandbox env (line 2179 of onboard.js) but bot tokens are not
Environment
- OS: macOS / Linux
- NemoClaw Version: v0.1.0
- Branch: main
- Runtime: Node.js v22
- Container / Orchestration Info: Docker sandbox via OpenShell
- Network Setup: N/A
Debug Output
# Trace the credential injection in onboard.js:
grep -n 'BOT_TOKEN\|DISCORD\|SLACK' bin/lib/onboard.js
# Lines 2180-2186: Bot tokens passed directly to sandbox env
# Compare with NVIDIA_API_KEY handling:
grep -n 'NVIDIA_API_KEY' bin/lib/onboard.js
# Line 2179: delete sandboxEnv.NVIDIA_API_KEY ← correctly scoped
# Bot tokens: no equivalent delete — they leak into sandboxLogs
# Inside sandbox — bot tokens visible to the agent:
$ env | grep TOKEN
DISCORD_BOT_TOKEN=MTIzNDU2Nzg5MDEyMzQ1Njc4OQ.XXXXXX.xxxxxxxxxx
SLACK_BOT_TOKEN=xoxb-1234567890-1234567890123-xxxxxxxxxxxx
# ↑ These should be passed via OpenShell credential provider, not env varsChecklist
- I confirmed this bug is reproducible
- I searched existing issues and this is not a duplicate