T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/navitia.py:34
- Finding
- Navitia credentials can be redirected to an arbitrary or plaintext host<![CDATA[ ## Vulnerability Details **File Location**: `scripts/navitia.py`, lines 34-49 **Vulnerability Type**: Unrestricted credential destination and missing transport validation **Risk Level**: High ### Vulnerable Code ```python def navitia_get(path: str, query: dict | None = None) -> dict: host = os.environ.get("NAVITIA_HOST", "https://api.navitia.io").rstrip("/") token = env("NAVITIA_TOKEN") qs = f"?{urllib.parse.urlencode(query)}" if query else "" url = f"{host}{path}{qs}" req = urllib.request.Request(url, method="GET") # Navitia accepts token as basic auth username, but the docs also show Authorization header usage. # We use Basic auth with token as username and empty password. auth = base64.b64encode(f"{token}:".encode("utf-8")).decode("ascii") req.add_header("Authorization", f"Basic {auth}") try: with urllib.request.urlopen(req, timeout=30) as resp: ``` ### Technical Analysis The Navitia token is Base64-encoded and placed in an HTTP Basic Authorization header. This encoding is required by the Basic authentication protocol and is not encryption. The encoded value is not directly printed to stdout, so the Base64 operation is not itself a covert output channel. The security issue is that `NAVITIA_HOST` is accepted without validating its scheme, hostname, port, or trust level. Consequently, the credential-bearing request may be sent to an arbitrary endpoint, including a plaintext `http://` endpoint. The HTTP client may also follow redirects, creating another opportunity for unintended credential disclosure depending on redirect handling. External network access and transmission of the token to Navitia are necessary for the declared transit-planning functionality. Allowing the token to be sent to any environment-selected destination exceeds the minimum privilege required. ### Attack Path 1. An attacker or compromised runtime configuration sets `NAVITIA_HOST` to an attacker-controlled URL, such as `h ...[truncated 937 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Parse the configured host using `urllib.parse.urlsplit`. - Require the `https` scheme for all credential-bearing requests. - Allowlist `api.navitia.io` in production. - If custom hosts are needed for testing, require a separate explicit development option and document that credentials must not be production credentials. - Reject URLs containing user information, fragments, unexpected ports, or malformed hostnames. - Prevent credential-bearing requests from following redirects to a different origin. - Continue keeping the token out of exception messages and normal output. - Consider centralizing URL validation so every API client applies the same policy. ]]>
