T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/pettracer_cli.py:41
- Finding
- Configurable REST API Origin Can Exfiltrate PetTracer Credentials and Bearer Tokens<![CDATA[ ## Vulnerability Details **File Location**: `scripts/pettracer_cli.py:41-42, 243-255, 339-366`; equivalent behavior also appears in `scripts/pettracer_watch.py:36-37, 64-77, 100-122` **Vulnerability Type**: Unvalidated security-sensitive endpoint configuration **Risk Level**: High ### Vulnerable Code ```python DEFAULT_API_BASE_URL = "https://portal.pettracer.com/api" API_BASE_URL = os.getenv("PETTRACER_API_BASE", DEFAULT_API_BASE_URL).rstrip("/") ``` ```python url = endpoint_or_url if endpoint_or_url.startswith("/"): url = f"{API_BASE_URL}{endpoint_or_url}" headers = { "Accept": "application/json, text/plain, */*", "Content-Type": "application/json", "User-Agent": USER_AGENT, "Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8", } if token: headers["Authorization"] = f"Bearer {token}" ``` ```python def get_token_or_login(*, username: Optional[str], password: Optional[str], timeout_s: int, retries: int) -> str: """Return bearer token from env or by logging in.""" token = _env_first("PETTRACER_TOKEN") if token: return token username = username or _env_first("PETTRACER_USERNAME", "PETTRACER_EMAIL") password = password or _env_first("PETTRACER_PASSWORD") if not username or not password: raise PetTracerAuthError( "Missing credentials. Set PETTRACER_TOKEN or (PETTRACER_USERNAME/PETTRACER_EMAIL + PETTRACER_PASSWORD)." ) payload = {"login": username, "password": password} resp = _request("POST", LOGIN_ENDPOINT, json_body=payload, timeout_s=timeout_s, retries=retries) if not isinstance(resp, dict): raise PetTracerAuthError("Login response was not a JSON object.") token = resp.get("access_token") or resp.get("token") or resp.get("id_token") if not token: raise PetTracerAuthError("Login response did not contain an access token.") return str(token) def fetch_devices(*, token: str, timeout_s: int, retries: int) -> List[Dict[str, Any]]: ...[truncated 2573 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Fix the production API origin to `https://portal.pettracer.com/api`. 2. If custom API origins are operationally necessary, parse them with `urllib.parse.urlsplit` and enforce: - Scheme exactly equal to `https`. - Hostname exactly equal to an explicit allowlist. - No URL user information. - No fragment. - Only an approved port and path prefix. 3. Reject invalid configuration before reading credentials or constructing an authenticated request. 4. Separate test-server support from production behavior. Require an explicit development-only flag and prohibit production tokens when it is enabled. 5. Apply the same validation centrally to both `pettracer_cli.py` and `pettracer_watch.py` to prevent implementation drift. 6. Consider certificate pinning only if PetTracer's deployment and certificate-rotation process can support it safely. ]]>
