T09 · Insecure Skill Coding Practices
Error
- Location
- scripts/email_ops.py:235
- Finding
- OAuth Credentials Can Be Transmitted to a Plaintext Token Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `scripts/email_ops.py`, lines 235-310 **Vulnerability Type**: Unencrypted transmission of sensitive OAuth credentials **Risk Level**: High ### Complete Code Snippet ```python token_endpoint = args.token_endpoint or os.getenv("EMAIL_TOKEN_ENDPOINT") or oauth_defaults.get("token_endpoint") client_id = args.client_id or os.getenv("EMAIL_CLIENT_ID") client_secret = args.client_secret or os.getenv("EMAIL_CLIENT_SECRET") scope = args.scope or os.getenv("EMAIL_SCOPE") or oauth_defaults.get("scope") ``` ```python def refresh_access_token(config: MailConfig) -> dict: if not config.refresh_token: raise ValueError("Missing refresh token.") if not config.token_endpoint: raise ValueError("Missing token endpoint. Set --token-endpoint or EMAIL_TOKEN_ENDPOINT.") if not config.client_id: raise ValueError("Missing client id. Set --client-id or EMAIL_CLIENT_ID.") payload = { "grant_type": "refresh_token", "refresh_token": config.refresh_token, "client_id": config.client_id, } if config.client_secret: payload["client_secret"] = config.client_secret if config.scope: payload["scope"] = config.scope data = urllib.parse.urlencode(payload).encode("utf-8") request = urllib.request.Request( config.token_endpoint, data=data, method="POST", headers={"Content-Type": "application/x-www-form-urlencoded"}, ) try: with urllib.request.urlopen(request, timeout=30) as response: body = response.read().decode("utf-8") ``` ### Technical Analysis The OAuth token endpoint can be supplied through `--token-endpoint` or `EMAIL_TOKEN_ENDPOINT`, but its URL scheme and destination are not validated before the request is made. The form-encoded POST body contains a reusable refresh token, client ID, optional client secret, and requested scope. If the endpoint uses `http://`, these credentials ...[truncated 1503 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse the configured endpoint with `urllib.parse.urlparse()` and require the `https` scheme. 2. Reject URLs containing embedded usernames or passwords. 3. Permit plaintext HTTP only for explicitly enabled loopback development endpoints such as `127.0.0.1` or `localhost`. 4. Disable redirects for token requests or validate every redirect target before forwarding credential-bearing requests. 5. Consider restricting token endpoints to known provider endpoints unless an explicit custom-endpoint mode is enabled. 6. Avoid including provider response bodies in errors because they may contain sensitive token-related data. 7. Add tests confirming that plaintext, malformed, credential-bearing, and unsafe redirect URLs are rejected. ]]>
