T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/analyze_stocks.py:63
- Finding
- Excessive Credential Access and Unrestricted Environment Disclosure to an External Skill<![CDATA[ ## Vulnerability Details **File Locations**: - `scripts/analyze_stocks.py:63-84` - `scripts/analyze_stocks_v2.py:33-59` - `scripts/analyze_stocks_v3.py:98-119` - `scripts/analyze_stocks_v3_detailed.py:73-94` **Vulnerability Type**: Excessive credential access and sensitive environment disclosure across a Skill boundary **Risk Level**: Medium ### Vulnerable Code #### `scripts/analyze_stocks.py:63-84` ```python em_api_key = os.environ.get('EM_API_KEY', '') if not em_api_key: try: with open('/root/.openclaw/workspace/vault/credentials/eastmoney.json', 'r') as f: config = json.load(f) em_api_key = config.get('em_api_key', '') except: return None if not em_api_key: return None try: import subprocess env = {**os.environ, 'EM_API_KEY': em_api_key} result = subprocess.run( ['python3', '/root/.openclaw/workspace/skills/mx-finance-data/scripts/get_data.py', '--query', f'{code.replace(".HK", "")}.HK EMA 均线'], capture_output=True, text=True, timeout=30, env=env ) ``` #### `scripts/analyze_stocks_v2.py:33-59` ```python em_api_key = os.environ.get('EM_API_KEY', '') if not em_api_key: # 从配置文件读取 try: with open('/root/.openclaw/workspace/vault/credentials/eastmoney.json', 'r') as f: config = json.load(f) em_api_key = config.get('em_api_key', '') except: pass if not em_api_key: print("警告:未找到 EM_API_KEY,使用 stock-price-query 作为备用", file=sys.stderr) return get_stock_data_tencent() # 构建查询语句 codes = [s['code'] for s in STOCKS] query = f"{','.join(codes)} 实时行情 涨跌幅 成交量" try: # 调用妙想数据脚本 result = subprocess.run( ['python3', '/root/.openclaw/workspace/skills/mx-finance-data/scripts/get_data.py', '--query', query], capture_output=True, text=True, timeout=60, env={**os.environ, 'EM_API_KEY': em_api_key} ) ``` #### `scripts/analyze_stocks_v3.py:9 ...[truncated 4374 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Remove automatic credential-vault discovery.** Do not read credentials directly from `/root/.openclaw/workspace/vault/credentials/`. Require the caller or platform to inject `EM_API_KEY` through an explicitly authorized secret-management mechanism. 2. **Construct a minimal subprocess environment.** Replace unrestricted environment copying with an allowlist: ```python child_env = { 'PATH': os.environ.get('PATH', ''), 'LANG': os.environ.get('LANG', 'C.UTF-8'), 'EM_API_KEY': em_api_key, } ``` Include only variables that the child process demonstrably requires. 3. **Avoid privileged absolute paths.** Make external Skill and output locations configurable or resolve them through an approved Skill registry. Do not assume execution under `/root`. 4. **Verify the external Skill.** Pin an audited version of `mx-finance-data`, verify its integrity before execution, and document its permitted network destinations and credential-handling behavior. 5. **Constrain the API credential.** Use a dedicated, narrowly scoped API key with rate limits, usage monitoring, rotation, and revocation support. 6. **Fail closed when credentials are unavailable.** Return a clear data-source error rather than searching unrelated filesystem locations for credentials. 7. **Validate child-process outputs.** Validate and constrain any Excel path returned by the external process before opening it, ensuring that it refers to an expected directory and regular file. ]]>
