T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/google-calendar-cli.py:225
- Finding
- OAuth Credentials Exposed Through Command-Line Arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/google-calendar-cli.py`, lines 225-227 **Vulnerability Type**: Sensitive credential exposure through process arguments and shell history **Risk Level**: Medium ### Vulnerable Code ```python parser.add_argument("--client-id", help="Google OAuth client ID (or GOOGLE_CLIENT_ID)") parser.add_argument("--client-secret", help="Google OAuth client secret (or GOOGLE_CLIENT_SECRET)") parser.add_argument("--refresh-token", help="Google OAuth refresh token (or GOOGLE_REFRESH_TOKEN)") ``` The insecure command-line credential mechanism is also explicitly documented in `README.md` and `SKILL.md`, increasing the likelihood that users will use it. ### Technical Analysis The CLI accepts the Google OAuth client secret and refresh token as command-line arguments. Command-line arguments may be exposed through: - Shell command history. - Process inspection facilities and process-monitoring tools. - Endpoint telemetry, audit logs, or job-runner logs that record complete commands. - CI/CD logs or automation configuration. - Diagnostic output collected by system administrators. A Google OAuth refresh token is a long-lived credential that can be exchanged for short-lived access tokens. Possession of the refresh token, together with the applicable OAuth client credentials, may allow an attacker to repeatedly obtain access tokens until the refresh token is revoked or otherwise invalidated. The application also supports environment variables, but retaining and documenting secret-bearing CLI flags creates an avoidable exposure path. The network transmission itself is necessary for the declared functionality and is restricted to the official HTTPS Google endpoints `oauth2.googleapis.com` and `www.googleapis.com`; no undisclosed destination was identified. ### Attack Path 1. A user follows the documented option and invokes the CLI with `--client-secret` and `--refresh-token`. 2. The complete command is retained in shell ...[truncated 1402 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove the `--client-secret` and `--refresh-token` command-line options so long-lived secrets cannot be supplied through process arguments. 2. Prefer an operating-system credential store or secret manager with access controls and auditability. 3. If interactive entry is required, use Python's `getpass.getpass()` so the secret is not echoed or included in command history. 4. For automation, support reading secrets from protected files or inherited file descriptors. Require restrictive file permissions and avoid printing secret values. 5. Environment variables may remain as a compatibility mechanism, but documentation should explain that they can still be exposed through process environments, crash diagnostics, or CI configuration. 6. Update `README.md`, `SKILL.md`, and CLI help text to remove examples or recommendations that encourage passing secrets as flags. 7. Never include OAuth credentials or token-endpoint response bodies in logs. Consider sanitizing authentication errors before displaying them. 8. Advise affected users to remove credential-bearing commands from shell history and revoke or rotate any refresh tokens and client secrets previously passed on the command line. ]]>
