T09 · Insecure Skill Coding Practices
- Location
scripts/ticktick_cli.py:232- Finding
OAuth Bearer Token Can Be Redirected to an Arbitrary Server
- Content
View full analysis
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
View remediation
