T09 · Insecure Skill Coding Practices
Warning
- Location
- bin/nordpool-fi.py:12
- Finding
- Unbounded Network Wait and Remote Response Size## Vulnerability Details **File Location**: `bin/nordpool-fi.py`, lines 12–13 **Vulnerability Type**: Unbounded external API request and response processing **Risk Level**: Medium ### Vulnerable Code ```python with urllib.request.urlopen(req) as response: return json.loads(response.read().decode()) ``` ### Technical Analysis The external HTTPS request does not specify a timeout. Consequently, an unavailable, slow, or malicious upstream service may leave the process waiting indefinitely. The code also calls `response.read()` without imposing a maximum response size. The complete response is loaded into memory before JSON decoding and parsing. If the API endpoint or its delivery path returns an excessively large body, the process may consume substantial memory or terminate due to resource exhaustion. TLS reduces the likelihood of an arbitrary network attacker modifying the response, but it does not protect against upstream compromise, service malfunction, DNS or trust-store compromise, or unexpectedly large legitimate responses. The code also does not validate the response content type or schema before processing it. ### Attack Path 1. An attacker compromises or gains control over the configured API endpoint or a trusted component in its delivery path. 2. When the skill requests `https://api.porssisahko.net/v2/latest-prices.json`, the attacker either delays the response indefinitely or returns an excessively large body. 3. Because no timeout is configured, a delayed response can block the skill process. 4. Because no response-size limit is enforced, an oversized response is loaded into memory in full. 5. The process experiences prolonged blocking, excessive memory consumption, or termination. ### Impact Assessment The issue can cause denial of service within the privileges and resource limits of the skill process. It does not directly grant code execution, elevated privileges, credential access, or persistence. Its scope is limited to process avai ...[truncated 109 chars]
- Remediation
- ## Remediation Suggestions - Configure a finite timeout when opening the URL, appropriate to the expected API latency. - Read the response incrementally and enforce a strict maximum byte count before decoding or parsing it. - Reject responses whose declared `Content-Length` exceeds the limit, while still enforcing the limit during streaming because that header may be absent or inaccurate. - Validate that the response has the expected JSON content type. - Validate the parsed object against an explicit schema, including the expected `prices` collection and required field types. - Handle timeout, size-limit, decoding, and schema-validation failures separately and return a controlled error. - Consider applying runtime memory and execution-time limits as an additional containment measure. A hardened implementation should follow this pattern: ```python MAX_RESPONSE_BYTES = 2 * 1024 * 1024 REQUEST_TIMEOUT_SECONDS = 10 with urllib.request.urlopen( req, timeout=REQUEST_TIMEOUT_SECONDS ) as response: content_type = response.headers.get_content_type() if content_type != "application/json": raise ValueError("Unexpected response content type") body = response.read(MAX_RESPONSE_BYTES + 1) if len(body) > MAX_RESPONSE_BYTES: raise ValueError("API response exceeds the permitted size") data = json.loads(body.decode("utf-8")) ```
