T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/ticktick_cli.py:232
- Finding
- OAuth Bearer Token Can Be Redirected to an Arbitrary Server<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ticktick_cli.py:232-236`; related token forwarding occurs in `scripts/ticktick_api_client.py:198-229` **Vulnerability Type**: Unrestricted authenticated API endpoint **Risk Level**: High ### Vulnerable Code ```python base_url: str = typer.Option( DEFAULT_BASE_URL, "--base-url", envvar=ENV_BASE_URL, help="API base URL.", ) ``` ```python def _headers(self) -> dict[str, str]: """Build request headers.""" return { "Authorization": f"Bearer {self.config.token}", "Accept": "application/json", "User-Agent": self.config.user_agent, } def _url(self, path: str) -> str: """Build the complete request URL.""" base_url = str(self.config.base_url) return f"{base_url.rstrip('/')}/{path.lstrip('/')}" def _request( self, method: str, path: str, params: dict[str, str] | None = None, payload: dict[str, Any] | list[Any] | None = None, ) -> httpx.Response: """Send an HTTP request.""" return self.session.request( method=method.upper(), url=self._url(path), params=params, json=payload, headers=self._headers(), timeout=self.config.timeout_seconds, ) ``` ### Technical Analysis The CLI allows the API base URL to be controlled through either `--base-url` or the `TICKTICK_BASE_URL` environment variable. The resulting URL is used for authenticated requests without restricting the destination to the official Dida365 API. Although the base URL is validated as an HTTP URL by Pydantic, that validation does not enforce the official hostname and permits unencrypted HTTP. The client consequently sends the OAuth bearer token to any destination supplied through the option or environment. This exceeds the minimum privileges required by the declared functionality. The Skill states that it connects directly to official Dida365 services, so forwarding authentication to arbitrary origins is un ...[truncated 921 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Remove the configurable base URL if custom endpoints are not required. - Otherwise, enforce HTTPS and an exact hostname allowlist such as `api.dida365.com`. - Reject URLs containing unexpected ports, credentials, fragments, or nonstandard schemes. - Configure redirect handling so authorization headers are never forwarded across origins. - If development endpoints are needed, require an explicit unsafe-development mode and a separate nonproduction token. - Do not allow an ambient environment variable to silently override the authenticated destination. ]]>
