T09 · Insecure Skill Coding Practices
- Location
scripts/withings.py:61- Finding
OAuth token files are not created atomically with restrictive permissions
- Content
View full analysis
dict: """Save tokens with expiry calculation.""" expiry = time.time() + data['expires_in'] payload = {**data, 'expiry_date': expiry} token_file = get_token_file(user_id) token_file.write_text(json.dumps(payload, indent=2)) try: os.chmod(token_file, 0o600) except Exception: pass return payload ``` The equivalent implementation in `scripts/withings_oauth_local.py` is: ```python def save_tokens(data: dict, user_id: str = 'default') -> dict: """Save tokens with expiry calculation.""" expiry = time.time() + data['expires_in'] payload = {**data, 'expiry_date': expiry} token_file = get_token_file(user_id) token_file.write_text(json.dumps(payload, indent=2)) # Secure permissions try: os.chmod(token_file, 0o600) except Exception: pass return payload ``` ### Technical Analysis Both scripts save OAuth access and refresh tokens by first calling `Path.write_text()` and only afterward changing the file mode to `0600`. When a token file is newly created, its initial permissions are determined by the process umask. With a common umask of `022`, the file may initially be created as `0644`. There is consequently a time-of-check/time-of-use window between file creation and `chmod()` during which another local user may be able to read the tokens. The scripts also suppress every exception raised by `chmod()`. If the permission change fails because of filesystem semantics, ownership, access-control rules, or another environmental condition, execution continues and the token file may remain overly permissive without notifying the u ...[truncated 2298 chars]- Remediation
View remediation
