T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/agent.py:14
- Finding
- Unrestricted server override can disclose API credentials and synchronized data<![CDATA[ ## Vulnerability Details **File Location**: `scripts/agent.py`, lines 14–27 **Vulnerability Type**: Unvalidated network destination and insecure transport configuration **Risk Level**: High ### Vulnerable Code ```python CLAWNED_SERVER = os.getenv("CLAWNED_SERVER", "https://api.clawned.io") CLAWNED_API_KEY = os.getenv("CLAWNED_API_KEY", "") def api_request(endpoint, data=None, method="POST"): if not CLAWNED_API_KEY: print("[!] CLAWNED_API_KEY not set. Get your key at https://clawned.io/settings"); sys.exit(1) body = json.dumps(data).encode() if data else None req = urllib.request.Request(f"{CLAWNED_SERVER}{endpoint}", data=body, method=method, headers={"Authorization": f"Bearer {CLAWNED_API_KEY}", "Content-Type": "application/json"}) try: with urllib.request.urlopen(req, timeout=60) as resp: return json.loads(resp.read().decode()) ``` ### Technical Analysis The destination used for authenticated API requests is taken directly from the optional `CLAWNED_SERVER` environment variable. The code does not parse or validate the URL, require HTTPS, constrain the destination host, or prevent requests to local and internal network addresses. Every request to the configured destination includes `CLAWNED_API_KEY` as a bearer token. Depending on the command, request bodies can also contain the hostname, operating-system family, agent identifier, and installed-skill inventory. Although support for a custom server may be intentional, accepting arbitrary destinations and plaintext HTTP exceeds the minimum network trust required for the default dashboard integration. In particular, an HTTP destination permits interception and modification by a network-positioned attacker. ### Attack Path 1. An attacker, compromised launcher, deployment configuration, or misleading setup instruction changes `CLAWNED_SERVER` to an attacker-controlled URL or an unencrypted HTTP endpoint. 2. The user invokes `sync`, `watch`, or a ...[truncated 989 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse the configured URL with `urllib.parse.urlparse` before constructing requests. 2. Require the `https` scheme and reject plaintext HTTP. 3. Allowlist `api.clawned.io` by default. 4. If self-hosted servers are supported, require an explicit opt-in and display the destination before sending credentials. 5. Reject URLs containing embedded user information, fragments, unexpected ports, or malformed hostnames. 6. Consider blocking loopback, link-local, and private network destinations unless local-server support is explicitly enabled. 7. Disable automatic cross-origin redirects for authenticated requests, or verify the destination again after every redirect. 8. Use narrowly scoped, revocable API tokens and document immediate token rotation if an untrusted server was configured. 9. Add automated tests covering HTTP URLs, malformed URLs, redirects, and attacker-controlled hosts. ]]>
