T09 · Insecure Skill Coding Practices
- Location
scripts/safe-update.sh:29- Finding
Environment Variables Are Interpolated Directly into Executable Python Source
- Content
View full analysis
Vulnerability Details
File Location:
scripts/safe-update.sh:29-35,48-78
Vulnerability Type: Python code injection through untrusted environment-derived configuration
Risk Level: HighVulnerable Code
bash CONFIG="${OPENCLAW_CONFIG:-$HOME/.openclaw/openclaw.json}" NPM_DIR="${OPENCLAW_NPM_DIR:-/opt/homebrew/lib/node_modules/openclaw}" APP_DIR="${OPENCLAW_APP_DIR:-/Applications/OpenClaw.app}" PLIST="${OPENCLAW_PLIST:-$HOME/Library/LaunchAgents/ai.openclaw.gateway.plist}" OC_BIN="${OPENCLAW_BIN:-/opt/homebrew/bin/openclaw}" GATEWAY_PORT="${OPENCLAW_GATEWAY_PORT:-18789}" SNAP_ROOT="${OPENCLAW_SNAP_ROOT:-/tmp/openclaw-rollback}" TG_BOT="${OPENCLAW_TG_BOT:-default}"bash BOT_TOKEN=$(python3 -c " import json, sys try: cfg = json.load(open('$CONFIG')) print(cfg['channels']['telegram']['accounts']['$TG_BOT']['botToken']) except Exception as e: sys.stderr.write(f'config error: {e}\n') sys.exit(1) " 2>/dev/null) # ---- Pull chat_id (env override > openclaw.json delivery target > fail) ---- CHAT_ID="${OPENCLAW_TG_CHAT_ID:-}" if [ -z "$CHAT_ID" ]; then CHAT_ID=$(python3 -c " import json, sys try: cfg = json.load(open('$CONFIG')) # Try common locations: delivery.targets[], channels.telegram.accounts.default.defaultChatId, etc. targets = cfg.get('delivery', {}).get('targets', []) for t in targets: if t.get('channel') == 'telegram' and t.get('to'): print(t['to']); sys.exit(0) # Fallback: defaultChatId on the bot account chat = cfg.get('channels', {}).get('telegram', {}).get('accounts', {}).get('$TG_BOT', {}).get('defaultChatId') if chat: print(chat); sys.exit(0) sys.exit(1) except Exception: sys.exit(1) " 2>/dev/null) fiTechnical Analysis
The supported
OPENCLAW_CONFIGandOPENCLAW_TG_BOTenvironment variables are inserted directly into source code passed ...[truncated 1580 chars]- Remediation
View remediation
Remediation Suggestions
-
Never interpolate shell variables into Python source.
-
Pass configuration values as positional arguments:
bash BOT_TOKEN=$(python3 - "$CONFIG" "$TG_BOT" <<'PY' import json import sys config_path = sys.argv[1] bot_name = sys.argv[2] with open(config_path, encoding="utf-8") as handle: cfg = json.load(handle) print(cfg["channels"]["telegram"]["accounts"][bot_name]["botToken"]) PY ) -
Apply the same data-only argument handling to the chat-ID lookup.
-
Validate bot account names against a conservative allowlist if OpenClaw account identifiers have a restricted format.
-
Validate that the configuration path resolves to an expected user-owned OpenClaw configuration file and is not a symlink to an unrelated file.
-
Preserve error handling without printing credentials or sensitive configuration values to logs.
-
