T09 · Insecure Skill Coding Practices
- Location
src/fb_client.py:61- Finding
Long-Lived Facebook Access Token Transmitted in URL Query Parameters
- Content
View full analysis
dict[str, str]: return {"access_token": self.access_token} async def _request( self, method: str, endpoint: str, *, params: dict[str, Any] | None = None, data: dict[str, Any] | None = None, ) -> dict[str, Any]: merged_params = {**self._auth_params(), **(params or {})} response = await self._client.request( method, endpoint, params=merged_params, data=data, ) ``` ### Technical Analysis Every Facebook Graph API request adds the long-lived Page access token to the URL query string through the `params` argument. Sending a credential to Facebook is necessary for the declared functionality, but placing it in the query string is not the minimum-risk authentication mechanism. Although HTTPS protects the URL while it is in transit, query strings are frequently captured by HTTP client diagnostics, reverse proxies, network monitoring products, exception reports, tracing platforms, and access logs. Anyone with access to such records may recover the complete token. The destination is the official Facebook Graph API, and no covert exfiltration destination was identified. The vulnerability is the avoidable exposure surface created by the authentication mechanism. ### Attack Path 1. An operator configures the Skill with a long-lived `FB_ACCESS_TOKEN`. 2. The Skill invokes any exposed Facebook tool. 3. `_auth_params()` returns the token and `_request()` includes it in `merged_params`. 4. `httpx` constructs a request URL containing `access_token=`. 5. A proxy, diagnostic hook, tracing system, exception collector, or URL logger records the complete request URL. 6. An attacker or unauthorized log reader extracts the token. 7. The attacker submits dir ...[truncated 910 chars]- Remediation
View remediation
