T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/lib/oauth2.py:82
- Finding
- OAuth2 secrets can be transmitted to an arbitrary or plaintext token endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lib/oauth2.py:82-94`, `scripts/lib/oauth2.py:112-117`, `scripts/lib/account_manager.py:142-150` **Vulnerability Type**: Unvalidated sensitive-data destination and server-side request forgery **Risk Level**: High ### Vulnerable Code ```python data = { "client_id": client_id, "client_secret": client_secret, "refresh_token": refresh_token, "grant_type": "refresh_token", } if scopes: data["scope"] = " ".join(scopes) encoded = urlencode(data).encode("utf-8") req = Request(token_uri, data=encoded, method="POST") req.add_header("Content-Type", "application/x-www-form-urlencoded") try: with urlopen(req, timeout=30) as resp: body = json.loads(resp.read().decode("utf-8")) ``` The endpoint and secrets are taken directly from configuration: ```python self.client_secret: str = credential_store.resolve( oauth2_config.get("client_secret", "") ) self.refresh_token: str = credential_store.resolve( oauth2_config.get("refresh_token", "") ) self.token_uri: str = oauth2_config.get("token_uri", "") ``` No validation is added when the manager is constructed: ```python def _get_oauth2_manager(self, cfg: dict[str, Any]) -> Any: """Create an OAuth2Manager if the config uses oauth2 auth.""" if cfg.get("auth") != "oauth2": return None oauth2_cfg = cfg.get("oauth2", {}) if not oauth2_cfg: return None from .oauth2 import OAuth2Manager return OAuth2Manager(oauth2_cfg) ``` ### Technical Analysis The OAuth2 refresh request includes the reusable refresh token and, when configured, the OAuth client secret. The destination is controlled entirely by `token_uri`; the implementation does not: - Require HTTPS. - Restrict the endpoint to an approved identity provider. - Reject loopback, private, link-local, or cloud metadata addresses. - Disable redirects or revalidate redirect destinations. Consequently, a malicious or compromised configuration can ...[truncated 1586 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse `token_uri` before making a request and require the `https` scheme. 2. Maintain an allowlist of approved OAuth providers or require an explicit administrative allowlist. 3. Resolve the hostname and reject loopback, private, reserved, multicast, and link-local addresses for both IPv4 and IPv6. 4. Disable automatic redirects, or apply the same scheme and destination validation to every redirect target. 5. Reject URIs containing embedded user information. 6. Avoid logging token endpoint query strings or response bodies. 7. Where practical, bind each account type to a known provider endpoint instead of accepting an arbitrary URI. 8. Treat configuration files as sensitive and require restrictive ownership and permissions. ]]>
