T09 · Insecure Skill Coding Practices
- Location
spotify.py:73- Finding
Spotify OAuth Tokens Are Stored Without Restrictive File Permissions
- Content
View full analysis
Path: out = Path(path) if path else DEFAULT_TOKEN_PATH out.parent.mkdir(parents=True, exist_ok=True) token["saved_at"] = int(time.time()) out.write_text(json.dumps(token, indent=2), encoding="utf-8") return out ``` ### Technical Analysis The token response saved by this function can contain a Spotify access token and a long-lived refresh token. The file is written using `Path.write_text()` without explicitly restricting its permissions. For a newly created file, the effective permissions depend on the process umask. With a common umask of `022`, the token file may be created with mode `0644`, making it readable by other local users. The parent directory is also created without an explicit owner-only mode. The default path is `~/.openclaw/spotify-token.json`, but callers can supply another path through `--spotify-token`. A user-provided location may be in a shared or otherwise insufficiently protected directory. ### Attack Path 1. The victim runs `python auth.py` and completes Spotify OAuth. 2. Spotify returns an access token and potentially a reusable refresh token. 3. `save_token()` writes these credentials to the token JSON file without enforcing owner-only permissions. 4. On a multi-user system with a permissive umask or shared token path, another local user or compromised process reads the file. 5. The attacker extracts the access or refresh token. 6. The attacker uses the granted Spotify OAuth scopes to make API requests until the token is revoked or otherwise invalidated. This path requires local filesystem access and permissions that allow the attacker to read the resulting file. ### Impact Assessment A stolen access token allows use of the permissions grante ...[truncated 538 chars]- Remediation
View remediation
