T09 · Insecure Skill Coding Practices
- Location
scripts/fetch_official_account_trends.py:58- Finding
API Key Disclosed in Debug Logs
- Content
View full analysis
Vulnerability Details
File Location:
scripts/fetch_official_account_trends.py, lines 58-77
Vulnerability Type: Sensitive credential exposure through diagnostic output
Risk Level: MediumVulnerable Code:
python # 从环境变量获取API Key api_key = os.environ.get("REDFOX_API_KEY") if not api_key: raise Exception("缺少 REDFOX_API_KEY 环境变量,请先配置 API Key。获取地址:https://redfox.hk/settings/api-keys?source=clawhub") # 请求头 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", "Accept": "application/json, text/plain, */*", "Accept-Language": "zh-CN,zh;q=0.9", "X-API-Key": api_key } last_error = None for attempt in range(max_retries): try: if debug: print(f"\n=== DEBUG: 第 {attempt + 1} 次尝试 ===", file=sys.stderr) print(f"URL: {url}", file=sys.stderr) print(f"Params: {params}", file=sys.stderr) print(f"Headers: {headers}", file=sys.stderr)Technical Analysis
The API credential is retrieved appropriately from the
REDFOX_API_KEYenvironment variable, but it is then placed into theheadersdictionary. When the user supplies the--debugoption, the entire dictionary is written to standard error without redaction. Consequently, the plaintext value of theX-API-Keyheader is exposed.Standard error is frequently captured by CI systems, agent execution transcripts, shell logging, centralized observability platforms, and support bundles. The exposure therefore persists beyond the immediate process and contradicts the project documentation's instruction not to expose keys in logs.
Attack Path
- A user configures a valid
REDFOX_API_KEYin the process environment. - An attacker, malicious instruction, or troubleshooting procedure persuades the user or agent to invoke the script with
--debug. - The script constructs ...[truncated 870 chars]
- A user configures a valid
- Remediation
View remediation
Remediation Suggestions
-
Never print the original authentication-header dictionary.
-
Construct a sanitized copy before diagnostic output:
python if debug: safe_headers = { key: ("***REDACTED***" if key.lower() in {"x-api-key", "authorization"} else value) for key, value in headers.items() } print(f"Headers: {safe_headers}", file=sys.stderr) -
Prefer an allowlist for logged metadata rather than redacting a full structure. For example, log only the URL, attempt number, timeout, and non-sensitive parameter names.
-
Add automated tests that run debug mode with a sentinel credential and assert that the sentinel never appears in either standard output or standard error.
-
Review historical logs for exposed keys and rotate any credential that may already have been recorded.
-
Apply server-side restrictions such as minimum required scopes, quotas, expiration, and straightforward revocation.
-
