T09 · Insecure Skill Coding Practices
- Location
skills/runninghub/scripts/runninghub_app.py:143- Finding
API Key Disclosure Through URL Query Parameters and Process Arguments
- Content
View full analysis
subprocess.CompletedProcess: cmd = ["curl", "-s", "-S", "--fail-with-body", "--max-time", str(timeout), url] return subprocess.run(cmd, capture_output=True, text=True) ``` ```python def get_node_info(api_key: str, webapp_id: str) -> list[dict]: url = f"{API_HOST}{NODE_INFO_PATH}?apiKey={api_key}&webappId={webapp_id}" result = curl_get(url) ``` ### Technical Analysis The `get_node_info` function embeds the complete RunningHub API key in a GET query parameter. The resulting URL is then supplied to `curl` as a command-line argument. Secrets placed in URLs can be exposed through: - Local process listings while `curl` is running. - HTTP server, reverse-proxy, gateway, or monitoring logs. - Diagnostic and error-reporting systems that record request URLs. - Shell or process auditing facilities. - Network observability systems that retain URL paths and query strings. HTTPS protects the request while it is transported, but it does not prevent disclosure through local process inspection or endpoint-side logging. The behavior is unnecessary because the same project already uses authorization headers for other API operations. ### Attack Path 1. A user or Agent invokes `runninghub_app.py --info` or `runninghub_app.py --run`. 2. The script resolves the API key from the command line, environment, or OpenClaw configuration. 3. `get_node_info` inserts the key into the URL as `?apiKey=`. 4. `curl_get` passes the full URL in the `curl` process argument list. 5. A local user with process-inspection access, or an operator with access to HTTP infrastructure logs, captures the URL. 6. The captured key is reused to invoke paid RunningHub API operations unde ...[truncated 484 chars]- Remediation
View remediation
subprocess.CompletedProcess: cmd = [ "curl", "-s", "-S", "--fail-with-body", "--max-time", str(timeout), "-H", f"Authorization: Bearer {api_key}", url, ] return subprocess.run(cmd, capture_output=True, text=True) ``` 3. If the endpoint does not support headers, use a protected POST body rather than a GET query string. 4. Prefer a Python HTTP library or protected curl configuration/input file so credentials do not appear in process arguments. 5. Redact query strings and authorization values from application, proxy, and diagnostic logs. 6. Rotate API keys that may previously have been exposed through this code. 7. Add automated tests that reject request URLs containing parameter names such as `apiKey`, `token`, or `secret`. ]]>
