T09 · Insecure Skill Coding Practices
- Location
scripts/raindrop_manager.py:42- Finding
OAuth Credentials Persisted Without Restrictive File Permissions
- Content
View full analysis
None: existing = load_dotenv(path) for key, value in values.items(): existing[key] = "" if value is None else str(value) lines = [f"{key}={existing[key]}" for key in sorted(existing.keys())] path.parent.mkdir(parents=True, exist_ok=True) path.write_text("\n".join(lines) + "\n", encoding="utf-8") ``` The function is called with sensitive OAuth credentials: ```python if not args.no_save: save_env_values( Path(creds["env_file"]), { "RAINDROP_CLIENT_ID": str(client_id), "RAINDROP_CLIENT_SECRET": str(client_secret), "RAINDROP_ACCESS_TOKEN": data.get("access_token"), "RAINDROP_REFRESH_TOKEN": data.get("refresh_token"), "RAINDROP_REDIRECT_URI": str(redirect_uri), }, ) ``` ### Technical Analysis OAuth client secrets, access tokens, and refresh tokens are written in plaintext to the configured environment file, which defaults to `~/.openclaw/raindrop.env`. The implementation creates the parent directory and writes the file but does not explicitly enforce owner-only permissions on either resource. The effective permissions therefore depend on the operating system, process umask, and permissions of any pre-existing file. On a multi-user system, a permissive configuration may allow another local account or process to read the credentials. A pre-existing file with insecure permissions remains insecure after `Path.write_text()` updates it. The storage is related to the declared OAuth functionality, but retaining the client secret and refresh token without permission hardenin ...[truncated 1345 chars]- Remediation
View remediation
