T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/refresh_token.py:28
- Finding
- OAuth Access Token Exposed Through Standard Output and Insecure Plaintext Storage## Vulnerability Details **File Location**: `scripts/refresh_token.py`, lines 28–49 **Vulnerability Type**: Plaintext sensitive-data exposure **Risk Level**: Medium **Vulnerable Code**: ```python # Update the secrets.env file env_path = os.path.expanduser('~/.config/google-calendar/secrets.env') # Read existing lines, replace or add GOOGLE_ACCESS_TOKEN lines = [] if os.path.exists(env_path): with open(env_path, 'r') as f: lines = f.readlines() new_lines = [] token_set = False for line in lines: if line.startswith('export GOOGLE_ACCESS_TOKEN='): new_lines.append(f'export GOOGLE_ACCESS_TOKEN={access_token}\n') token_set = True else: new_lines.append(line) if not token_set: new_lines.append(f'export GOOGLE_ACCESS_TOKEN={access_token}\n') with open(env_path, 'w') as f: f.writelines(new_lines) print(json.dumps(resp_data, indent=2)) ``` ### Technical Analysis The OAuth access token returned by Google is written in plaintext to `~/.config/google-calendar/secrets.env`. The script does not create the parent directory with restrictive permissions, explicitly set the file mode to `0600`, verify existing file ownership, or perform an atomic replacement. The entire OAuth response is also printed to standard output. Because the response contains `access_token`, the credential may be captured by terminal history tooling, agent transcripts, automation logs, CI logs, process wrappers, or redirected output files. This behavior exceeds the minimum disclosure necessary for token refresh. Persisting an access token may be operationally useful, but printing it is unnecessary, and storage should use a protected secret-management mechanism. The separate transmission of the client ID, client secret, and refresh token to `https://oauth2.googleapis.com/token` is expected OAuth behavior and is necessary for refresh-token exchange. No transmission to an unknown or attacker- ...[truncated 1220 chars]
- Remediation
- ## Remediation Suggestions - Do not print the complete OAuth response. Emit only non-sensitive status information, such as successful refresh and token expiry. - Store the token using the documented OpenClaw secret-management facility instead of a plaintext environment file. - If file storage is unavoidable, create the configuration directory with mode `0700` and the token file with mode `0600`. - Verify that an existing token file is a regular file owned by the current user and is not a symbolic link. - Write to a securely created temporary file in the same directory, apply restrictive permissions, flush it, and atomically replace the destination. - Avoid preserving access tokens longer than operationally necessary, and document revocation and rotation procedures. - Ensure logs, exception handlers, and diagnostic output redact `access_token`, `refresh_token`, `client_secret`, and authorization headers.
