T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/ip_lookup.py:98
- Finding
- Geolocation Target and Results Transmitted over Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ip_lookup.py`, lines 98-106 **Vulnerability Type**: Plaintext transmission and unauthenticated network response **Risk Level**: Medium **Classification**: T09: Insecure Skill Coding Practices ### Vulnerable Code ```python def fetch_geo(ip: str) -> dict: """ip-api.com geolocation + ASN. Falls back to ipwho.is.""" fields = ("status,message,country,countryCode,regionName,city,zip," "lat,lon,timezone,isp,org,as,asname,mobile,proxy,hosting,query") data = fetch(f"http://ip-api.com/json/{ip}", params={"fields": fields}) if data and data.get("status") == "success": return {"_source": "ip-api.com", **data} data2 = fetch(f"https://ipwho.is/{ip}") ``` ### Technical Analysis The primary geolocation request uses `http://ip-api.com` rather than an HTTPS endpoint. Consequently, neither the confidentiality of the requested IP address nor the authenticity and integrity of the returned geolocation data is protected by TLS. A passive network observer can identify which IP addresses the user is investigating. An active on-path attacker—such as an operator of a malicious wireless access point, compromised gateway, or hostile network intermediary—can intercept the request and return attacker-controlled JSON. The generic `fetch()` function accepts and parses any syntactically valid JSON response. `fetch_geo()` only verifies that the response contains `"status": "success"` before treating all remaining fields as trusted geolocation intelligence. An attacker can therefore forge fields such as country, organization, ASN, ISP, proxy status, and hosting status. The HTTPS fallback does not mitigate this issue when an attacker supplies a valid-looking successful response to the initial HTTP request, because the fallback is only used when the first response fails or reports an unsuccessful status. ### Attack Path 1. A user invokes the Skill to investigate an IP address or hostn ...[truncated 1316 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace the plaintext endpoint with a geolocation provider that supports HTTPS: ```python data = fetch(f"https://<trusted-geolocation-provider>/{ip}", params={"fields": fields}) ``` 2. If the selected provider does not offer HTTPS under the applicable service tier, do not silently use its HTTP endpoint. Use the existing HTTPS `ipwho.is` service as the primary provider or select another HTTPS-capable service. 3. If plaintext access must be retained for compatibility, disable it by default and require an explicit, clearly documented command-line opt-in that warns users about target disclosure and response manipulation. 4. Enforce HTTPS centrally in `fetch()` so future callers cannot accidentally introduce plaintext requests: ```python def fetch(url: str, params: dict | None = None, headers: dict | None = None, timeout: int = 8) -> dict | None: parsed = urllib.parse.urlparse(url) if parsed.scheme != "https": raise ValueError("Refusing non-HTTPS network request") # Continue constructing and sending the request. ``` 5. Retain strict request timeouts and add response-size limits and schema/type validation. Schema validation will reduce malformed-data risks, although it cannot replace TLS for server authentication and response integrity. ]]>
