T09 · Insecure Skill Coding Practices
Warning
- Location
- SKILL.md:51
- Finding
- OAuth Credentials Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 51-55 **Vulnerability Type**: OAuth secret exposure through process arguments **Risk Level**: Medium ### Vulnerable Code ```bash GMAIL_ACCESS_TOKEN=$(curl -s -X POST "https://oauth2.googleapis.com/token" \ -d "client_id=$GMAIL_CLIENT_ID" \ -d "client_secret=$GMAIL_CLIENT_SECRET" \ -d "refresh_token=$GMAIL_REFRESH_TOKEN" \ -d "grant_type=refresh_token" | jq -r '.access_token') ``` ### Technical Analysis The shell expands `GMAIL_CLIENT_ID`, `GMAIL_CLIENT_SECRET`, and `GMAIL_REFRESH_TOKEN` before starting `curl`. Consequently, the expanded secrets are passed as command-line arguments. Although the credentials are transmitted over HTTPS to Google's legitimate OAuth endpoint, command-line arguments may be exposed through local process inspection, execution tracing, diagnostic tooling, audit systems, or logs that record expanded commands. A refresh token is particularly sensitive because it is long-lived and can be exchanged repeatedly for access tokens until revoked. The network transfer itself is necessary for OAuth token refresh. The vulnerability is the mechanism used to supply the credentials to `curl`, not the use of Google's OAuth service. ### Attack Path 1. The Skill refreshes the Gmail access token using the documented command. 2. A local process, monitoring agent, or user with sufficient process-inspection privileges observes the active `curl` command or captures an execution trace. 3. The expanded client secret and refresh token are recovered from the command-line arguments. 4. The attacker submits the stolen values to `https://oauth2.googleapis.com/token`. 5. Google returns an access token if the credentials remain valid. 6. The attacker uses that token to access Gmail operations permitted by the OAuth grants. This path requires local process, telemetry, tracing, or command-logging visibility; the Skill does not independently transmit credentials to an untrusted dom ...[truncated 574 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Avoid placing client secrets and refresh tokens directly in command-line arguments. - Provide the request body through standard input so secrets are not exposed in `curl` process arguments. For example: ```bash TOKEN_RESPONSE=$( printf '%s' \ "client_id=$(printf '%s' "$GMAIL_CLIENT_ID" | jq -sRr @uri)&client_secret=$(printf '%s' "$GMAIL_CLIENT_SECRET" | jq -sRr @uri)&refresh_token=$(printf '%s' "$GMAIL_REFRESH_TOKEN" | jq -sRr @uri)&grant_type=refresh_token" | curl --silent --show-error --fail \ -X POST \ -H "Content-Type: application/x-www-form-urlencoded" \ --data-binary @- \ "https://oauth2.googleapis.com/token" ) GMAIL_ACCESS_TOKEN=$(printf '%s' "$TOKEN_RESPONSE" | jq -er '.access_token') ``` - Disable shell tracing around credential-processing commands and ensure secrets are never written to logs. - Validate that all required environment variables are present before attempting a refresh. - Use `curl --fail --show-error` and `jq -e` so authentication errors cannot silently produce an invalid token. - Keep credential-bearing environment variables available only to the Skill process and avoid exposing them to unrelated child processes. - Revoke and rotate the refresh token and client secret if process telemetry or command logs may already have captured them. ]]>
