T09 · Insecure Skill Coding Practices
Note
- Location
- scripts/cn_todo_today.py:24
- Finding
- Todo Data File Is Created Without Restrictive Permissions or Symlink Protection## Vulnerability Details **File Location**: `scripts/cn_todo_today.py`, lines 24-26 **Vulnerability Type**: Insecure local file creation and symbolic-link following **Risk Level**: Low ```python with open(TODO_FILE, 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2) ``` ### Technical Analysis The application stores todo data in the fixed path `~/.cn_todo_today.json` using the standard `open()` function without explicitly applying restrictive permissions. The permissions assigned to a newly created file therefore depend on the process umask. Under a commonly used umask of `022`, the file can be created with mode `0644`, allowing other local users to read its contents when directory permissions permit traversal. The operation also follows symbolic links. If an attacker can manipulate the target path before the application saves data, the attacker can replace `~/.cn_todo_today.json` with a symbolic link to another file writable by the invoking user. A subsequent save will truncate that target and replace its contents with JSON data. The implementation does not use exclusive creation, a no-follow option, atomic replacement, or validation that the destination is a regular file owned by the current user. ### Attack Path **Information disclosure path:** 1. The user runs an operation that invokes `save_todos()`. 2. The application creates `~/.cn_todo_today.json` with permissions derived from the current umask. 3. If those permissions allow local reads and the home directory is traversable, another local user reads the file. 4. Todo descriptions and their creation or completion timestamps are disclosed. **Symbolic-link overwrite path:** 1. An attacker with the ability to manipulate `~/.cn_todo_today.json` removes or renames the existing file. 2. The attacker creates a symbolic link at that path pointing to another file writable by the victim user. 3. The victim invokes an operation that sa ...[truncated 930 chars]
- Remediation
- ## Remediation Suggestions - Create the data file with owner-only permissions (`0600`) rather than relying on the process umask. - Write updates to a securely created temporary file in the same directory and atomically replace the destination with `os.replace()`. - Create the temporary file using `tempfile.mkstemp()` or `tempfile.NamedTemporaryFile()` with restrictive permissions. - Reject symbolic links by using `os.open()` with `O_NOFOLLOW` where supported and verify with `os.fstat()` that the opened object is a regular file. - Verify that an existing destination is owned by the current user before replacing it. - Flush buffered data and call `os.fsync()` before atomic replacement when durability is required. - Apply `os.chmod(TODO_FILE, 0o600)` to securely migrate an existing regular data file, after validating its ownership and type.
