T09 · Insecure Skill Coding Practices
- Location
scripts/gdrive_sa.py:97- Finding
Unvalidated Service-Account Token URI Enables SSRF and Disclosure of Signed Authentication Material
- Content
View full analysis
str: now = int(time.time()) header = {"alg": "RS256", "typ": "JWT"} claim = { "iss": sa["client_email"], "scope": scope, "aud": sa.get("token_uri", "https://oauth2.googleapis.com/token"), "iat": now, "exp": now + 3600, } if subject: claim["sub"] = subject signing_input = f"{b64url(json.dumps(header, separators=(',', ':')).encode())}.{b64url(json.dumps(claim, separators=(',', ':')).encode())}" signature = sign_rs256(signing_input.encode("ascii"), sa["private_key"]) assertion = f"{signing_input}.{b64url(signature)}" payload = urllib.parse.urlencode( { "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", "assertion": assertion, } ).encode("utf-8") req = urllib.request.Request( sa.get("token_uri", "https://oauth2.googleapis.com/token"), data=payload, headers={"Content-Type": "application/x-www-form-urlencoded"}, method="POST", ) try: with urllib.request.urlopen(req) as resp: data = json.loads(resp.read().decode("utf-8")) except urllib.error.HTTPError as exc: detail = exc.read().decode("utf-8", "replace") raise SystemExit(f"Token exchange failed: HTTP {exc.code}: {detail}") return data["access_token"] ``` ### Technical Analysis The service-account JSON is loaded from `GOOGLE_SERVICE_ACCOUNT_KEY`, which may either contain JSON directly or identify a local JSON file. Its optional `token_uri` property is used without validation as: 1. The `aud` claim of a newly signed JWT assertion. 2. The destination of an outbound HTTP POST request. No check restric ...[truncated 2570 chars]- Remediation
View remediation
