T09 · Insecure Skill Coding Practices
Warning
- Location
- skill.md:40
- Finding
- Predictable Temporary File and Symlink-Following Output Write## Vulnerability Details **File Location**: `skill.md:40-41` and `generate_ppt.py:245` **Vulnerability Type**: Predictable temporary file and unsafe symlink-following file operation **Risk Level**: Medium **Complete Code Snippet**: ```bash OUTFILE="/tmp/popai_ppt_$(date +%s).jsonl" touch "$OUTFILE" ``` ```python out = open(output_file, "a") if output_file else None ``` ### Technical Analysis The documented workflow constructs an output pathname from the current timestamp in the shared `/tmp` directory. The filename is predictable, and `touch` does not ensure exclusive creation or verify that the path is a regular file owned by the invoking user. The Python implementation subsequently opens the caller-supplied path in append mode. Python's standard `open()` follows symbolic links by default. It does not use exclusive creation, `O_NOFOLLOW`, ownership validation, or file-type validation. Consequently, another local user could pre-create the predicted path as a symbolic link or race to replace the touched file before the Python process opens it. The process would then append PopAI event output to the symlink target using the invoking user's filesystem privileges. ### Attack Path 1. An attacker with local access monitors or predicts when the documented workflow will run. 2. The attacker derives the expected path, such as `/tmp/popai_ppt_<current_timestamp>.jsonl`. 3. The attacker pre-creates that path as a symbolic link, or replaces the file after `touch` and before `open()`. 4. The link points to a target file writable by the victim account or to an attacker-controlled collection file. 5. The Skill invokes `generate_ppt.py` with the predictable path through `--output`. 6. `open(output_file, "a")` follows the symbolic link. 7. Parsed API events, summaries, presentation URLs, or attacker-influenced content are appended to the target. ### Impact Assessment Exploitation does not grant privileges beyond ...[truncated 618 chars]
- Remediation
- ## Remediation Suggestions - Replace timestamp-derived filenames with securely and atomically created temporary files: ```bash OUTFILE="$(mktemp /tmp/popai_ppt.XXXXXXXXXX.jsonl)" chmod 600 "$OUTFILE" ``` - Prefer creating the file in Python with `tempfile.NamedTemporaryFile(delete=False)` or `tempfile.mkstemp()`, which provides exclusive creation and a randomized name. - Open user-supplied output paths with operating-system flags such as `O_NOFOLLOW`, `O_CREAT`, and, when creating a new file, `O_EXCL`. - Before writing, use `os.lstat()` or equivalent checks to reject symbolic links and non-regular files. - Verify that an existing output file is owned by the effective user and has restrictive permissions. - Keep the temporary file descriptor open from creation through use instead of creating a pathname and reopening it later, eliminating the time-of-check/time-of-use race. - Store temporary output in a private directory with mode `0700` when possible.
