T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/ms_todo_auth.py:99
- Finding
- OAuth Tokens Stored Without Explicit Owner-Only File Permissions## Vulnerability Details **File Location**: `scripts/ms_todo_auth.py`, lines 99–101 **Vulnerability Type**: Insecure storage of OAuth access and refresh tokens **Risk Level**: Medium ### Vulnerable Code ```python def write_json(path: Path, payload: dict) -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8") ``` This function is used to persist complete OAuth responses in the following flows: ```python write_and_print_json(TOKEN_FILE, payload, redact_tokens=True) ``` Although token values are redacted from normal console output, the complete payload—including access tokens, refresh tokens, and potentially ID tokens—is written to `token.json`. ### Technical Analysis The configuration directory and token file are created without explicit owner-only permissions. Their effective permissions therefore depend on the process umask and any pre-existing filesystem objects. Under a permissive umask or unsafe configuration-directory override, another local account may be able to read the token file. The destination can also be controlled through environment variables such as `MS_TODO_CONFIG_DIR` and `MS_TODO_TOKEN_FILE`. The implementation does not verify destination ownership, permissions, or whether the destination is a symbolic link. It also does not use an atomic, exclusive file-creation operation. These omissions increase the risk when the helper runs in a shared or adversarial local environment. The network transmission detected by the pre-scan is otherwise consistent with the declared functionality: device codes and refresh tokens are sent to Microsoft OAuth endpoints under `login.microsoftonline.com`. The requested `Tasks.ReadWrite` permission is necessary for the documented task creation, modification, completion, and deletion features, while `offline_access` supports the documented token-refresh feature. ### Attack Path 1. A victim runs `device-code` followed by `poll-tok ...[truncated 1520 chars]
- Remediation
- ## Remediation Suggestions 1. Create the configuration directory with owner-only permissions (`0700` on POSIX systems), and verify that existing directories are owned by the current user and are not writable by untrusted users. 2. Create token and device-code files with owner-only permissions (`0600` on POSIX systems) rather than relying on the process umask. 3. Write secrets atomically: - Create a temporary file in the same trusted directory using exclusive creation. - Apply restrictive permissions before writing sensitive content. - Flush and securely replace the destination. 4. Reject symbolic links and other unexpected file types for secret destinations. Where supported, use no-follow semantics during file creation. 5. Validate environment-overridden paths before storing credentials. Warn or fail if the destination is in a shared, world-readable, or world-writable directory. 6. On Windows, apply an ACL that grants access only to the current user rather than relying solely on generic file-creation behavior. 7. Prefer an OS-native credential store or keychain for refresh tokens when practical. 8. Preserve the existing stdout redaction behavior and clearly warn users that `access-token` intentionally emits a bearer token that must not be logged or exposed.
