T09 · Insecure Skill Coding Practices
- Location
scripts/whoop_oauth_login.py:37- Finding
OAuth Authorization Flow Lacks State Validation and PKCE Binding
- Content
View full analysis
str: s = user_input.strip() if s.startswith("http://") or s.startswith("https://"): u = urllib.parse.urlparse(s) q = urllib.parse.parse_qs(u.query) code = (q.get("code") or [None])[0] if code: return code raise SystemExit("Could not find ?code= in the pasted redirect URL") return s ``` ```python q = urllib.parse.parse_qs(parsed.query) code = (q.get("code") or [None])[0] if code: got["code"] = code ``` ```python params = { "client_id": client_id, "redirect_uri": redirect_uri, "response_type": "code", "scope": scopes, } auth_url = OAUTH_AUTH_URL + "?" + urllib.parse.urlencode(params) ``` ```python tok = exchange_code_for_token( code=code, client_id=client_id, client_secret=client_secret, redirect_uri=redirect_uri, ) ``` ```python def exchange_code_for_token(*, code: str, client_id: str, client_secret: str, redirect_uri: str) -> Dict[str, Any]: tok = _post_form( OAUTH_TOKEN_URL, { "grant_type": "authorization_code", "code": code, "client_id": client_id, "client_secret": client_secret, "redirect_uri": redirect_uri, }, ) _annotate_expiry(tok) return tok ``` ### Technical Analysis The authorization request does not include a cryptographically random OAuth `state` parameter. Neither the copy-and-paste callback parser nor the loopback HTTP handler validates that a callback belongs to the authorization request initiated by the current process. The implementation also does not use PKCE. It therefore has no `code_challenge` in the authorization request and no corresp ...[truncated 1767 chars]- Remediation
View remediation
