T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/sync-google-tasks.py:40
- Finding
- OAuth Refresh Token Is Stored Without Enforced Restrictive Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/sync-google-tasks.py`, lines 40–41 **Vulnerability Type**: Insecure local credential storage **Risk Level**: Medium ### Vulnerable Code ```python with open(token_path, 'w') as token: token.write(creds.to_json()) ``` ### Technical Analysis The script stores Google OAuth credentials in `~/.openclaw/google-tasks/token.json` using the process's default file-creation permissions. The serialized credentials may contain an access token and a reusable refresh token. Because the script does not explicitly create the file with mode `0600` or validate the containing directory's permissions, the effective access controls depend on the user's `umask` and existing filesystem configuration. On a shared system or one with permissive defaults, another local account or process may be able to read the token. The Google scope is appropriately limited to `https://www.googleapis.com/auth/tasks.readonly`, so the token does not grant task modification privileges. Nevertheless, it can expose private task titles, notes, links, and metadata. ### Attack Path 1. A user authenticates the Skill with Google Tasks. 2. The script serializes the OAuth credentials to `~/.openclaw/google-tasks/token.json`. 3. The file is created under a permissive `umask`, or its parent directory permits access by another local user. 4. A local attacker or compromised process reads `token.json`. 5. The attacker extracts the refresh token and exchanges it for a new Google access token. 6. The attacker uses the read-only Google Tasks API scope to retrieve the victim's task data. This attack requires local filesystem access or execution in another process that can read the affected path. ### Impact Assessment Successful exploitation can disclose the victim's Google Tasks data, including task titles, notes, due dates, links, and list metadata. The obtained privileges are limited by the configured read-only Tasks scope; no evidence indicates ...[truncated 66 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Create `~/.openclaw/google-tasks` with mode `0700`. - Create or replace `token.json` atomically with mode `0600`. - Validate existing token and directory permissions before reading credentials. - Refuse to load a token file that is owned by another user or is group/world-readable. - Avoid relying solely on the process-wide `umask`. Example hardened approach: ```python os.makedirs(creds_dir, mode=0o700, exist_ok=True) os.chmod(creds_dir, 0o700) flags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC fd = os.open(token_path, flags, 0o600) with os.fdopen(fd, 'w') as token: token.write(creds.to_json()) os.chmod(token_path, 0o600) ``` For stronger crash safety, write to a securely created temporary file in the same directory, apply mode `0600`, flush and synchronize it, and atomically replace the destination. ]]>
