T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/run_tracker.py:85
- Finding
- Automatic API Credential Discovery Exposes the Secret in Process Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/run_tracker.py`, lines 85–128; invocation occurs at lines 416 and 431 **Vulnerability Type**: Automatic credential access and insecure secret handling **Risk Level**: Medium ### Vulnerable Code ```python def get_openrouter_api_key(): """ Resolve OpenRouter API key. Priority: env var > OpenClaw auth-profiles.json """ key = os.environ.get("OPENROUTER_API_KEY") if key: return key auth_candidates = [ os.path.expanduser("~/.openclaw/agents/main/agent/auth-profiles.json"), "/data/.openclaw/agents/main/agent/auth-profiles.json", "/root/.openclaw/agents/main/agent/auth-profiles.json", ] for auth_path in auth_candidates: if os.path.exists(auth_path): try: with open(auth_path) as f: data = json.load(f) key = data.get("profiles", {}).get("openrouter:default", {}).get("key") if key: return key except Exception: continue return None def get_openrouter_key_info(api_key): """ Fetch key info from /api/v1/auth/key. Returns dict with: usage, usage_daily, usage_weekly, usage_monthly, limit, limit_remaining. """ if not api_key: return None try: cmd = ["curl", "-s", "-H", f"Authorization: Bearer {api_key}", "https://openrouter.ai/api/v1/auth/key"] result = subprocess.run(cmd, capture_output=True, text=True, timeout=20) if result.returncode == 0: return json.loads(result.stdout).get("data", {}) except Exception: pass return None ``` The credential lookup and network request are invoked during ordinary report generation: ```python api_key = get_openrouter_api_key() ... key_info = get_openrouter_key_info(api_key) ``` ### Technical Analysis Every normal execution of `run_tracker.py` automatically searches the env ...[truncated 2219 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Make account-level OpenRouter enrichment explicitly opt-in, for example: ```bash python3 scripts/run_tracker.py --include-key-info ``` Local reports should not access credentials or the network unless that option is supplied. 2. Replace the external `curl` subprocess with an in-process HTTPS client. Set the authorization header through the client API so that the secret is not placed in child-process arguments. 3. Add a network-disable option and default it to disabled for scheduled and local database reports. 4. Avoid searching multiple privileged or unrelated account locations automatically. Prefer an explicitly configured credential source and validate file ownership and restrictive permissions before reading it. 5. Document clearly: - which credential is accessed; - which endpoint receives it; - when network access occurs; - which report fields depend on the remote request. 6. Ensure errors, debug output, telemetry, and exception logs never include authorization headers or the credential value. 7. Use a dedicated, least-privileged OpenRouter key if the remote account summary is enabled, and rotate any key suspected of exposure through process monitoring. ]]>
