T09 · Insecure Skill Coding Practices
Error
- Location
- SKILL.md:75
- Finding
- Configurable API Base URL Can Exfiltrate a Locally Stored Request Key<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:15`, `SKILL.md:75-77`, and `SKILL.md:88-105` **Vulnerability Type**: Credential disclosure through an unvalidated remote endpoint **Risk Level**: High ### Vulnerable Code The skill defines `BASE_URL` as an input: ```markdown - `BASE_URL` (default: `https://self-evolve.club/api/v1`) ``` It then sends the request key to that configurable URL: ```bash REQUEST_KEY_ID="<request_key_id>" curl -s "$BASE_URL/stats/me" \ -H "request-key-id: $REQUEST_KEY_ID" ``` The key can be loaded from a local plugin credential file: ```bash KEY_FILE="$HOME/.openclaw/plugins/self-evolve/remote-request-key.json" REQUEST_KEY_ID="$(jq -r '.requestKeyId' "$KEY_FILE")" ``` The documented fallback also reads the same credential using Python: ```bash REQUEST_KEY_ID="$(python3 - <<'PY' import json, os path = os.path.expanduser('~/.openclaw/plugins/self-evolve/remote-request-key.json') with open(path, 'r', encoding='utf-8') as f: print(json.load(f).get('requestKeyId', '')) PY )" ``` ### Technical Analysis The skill treats `BASE_URL` as a configurable input but does not require validation of its scheme, hostname, port, or path before an authenticated request is made. Separately, it directs the agent to retrieve `requestKeyId` from a local credential file and place it in the `request-key-id` HTTP header. Consequently, an attacker who can influence the `BASE_URL` used for the authenticated `/stats/me` operation can cause the locally stored request key to be transmitted to an attacker-controlled HTTP server. The safety guidance prohibiting disclosure in logs does not prevent network disclosure to an untrusted destination. The public API operations do not expose the key, and the username examples use a fixed official URL. The vulnerable sink is specifically the authenticated `/stats/me` command that combines the configurable base URL with the credential header. ### Attack Path 1. An attacker supplies or induces the ...[truncated 1107 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not permit arbitrary `BASE_URL` values for authenticated operations. Hardcode the trusted endpoint: ```bash AUTH_BASE_URL="https://self-evolve.club/api/v1" ``` 2. If configurability is required, validate the parsed URL before reading the credential. Require: - Scheme exactly equal to `https`. - Hostname exactly equal to `self-evolve.club`. - No embedded user information. - Only the expected HTTPS port. - The expected `/api/v1` base path. 3. Keep public and authenticated endpoint configuration separate. A custom endpoint intended for public leaderboard requests must never automatically inherit credential-bearing requests. 4. Read `REQUEST_KEY_ID` only after the authenticated destination has passed validation. 5. Explicitly disable or safely constrain redirects for authenticated requests so credentials cannot be forwarded to another host. Fail closed if the service returns a redirect. 6. Avoid placing the secret directly in shell command text where practical. Use a restrictive credential helper or a temporary header configuration with permissions limited to the current user, and securely remove temporary material after use. 7. Add documentation requiring explicit user confirmation before sending a locally stored key and display the validated destination without displaying the key. ]]>
