T09 · Insecure Skill Coding Practices
- Location
scripts/ini_align.py:127- Finding
Input Files Can Be Truncated Through Unsafe Output Path Handling
- Content
View full analysis
Vulnerability Details
File Location:
scripts/ini_align.py:127-128
Vulnerability Type: Unrestricted file overwrite and input/output path aliasing
Risk Level: MediumVulnerable Code
python # Write output with open(output_path, 'w', encoding='utf-8') as f: f.write('\n'.join(lines))The command-line entry point passes the user-provided output path directly into this operation:
python align_ini(sys.argv[1], sys.argv[2], sys.argv[3])Technical Analysis
The output file is opened in
wmode without verifying that it is distinct from the source and target files. Opening an existing file in this mode truncates it before writing the generated result.This conflicts with the documented guarantee in
SKILL.mdthat the source and target are never modified and that the output must never overwrite either input. The script does not enforce that guarantee.A direct string comparison would not be sufficient because different path strings can identify the same file. Aliasing can occur through:
- Identical path arguments
- Relative and absolute forms of the same path
- Symbolic links
- Hard links
- Paths containing components such as
..
The output operation also overwrites any other existing file writable by the current process. There is no exclusive-creation or no-follow protection.
Attack Path
-
An attacker or user supplies valid source and target INI files.
-
The output argument is set to the source path, target path, or an alias of either file. For example:
bash python scripts/ini_align.py source.ini target.ini target.ini -
Both inputs are parsed before the output is opened, so execution appears to proceed normally.
-
At line 127, the aliased input is opened in
wmode and immediately truncated. -
The generated content is written over the original input, causing irreversible loss of comments, formatting, duplicate entries, and pot ...[truncated 750 chars]
- Remediation
View remediation
Remediation Suggestions
- Reject an output path that identifies the same file as either input. For existing paths, use
os.path.samefile()so symbolic links and hard links are detected. - Refuse to overwrite any existing output file if the documented behavior requires creation of a new file.
- Open the output using exclusive creation, such as mode
x, rather than modew. - For stronger race-condition resistance on supported platforms, use
os.open()withO_CREAT,O_EXCL, andO_NOFOLLOW, then wrap the resulting descriptor withos.fdopen(). - Validate and normalize paths before processing, while recognizing that normalization alone does not detect hard links.
- Emit a clear error and exit without writing when the output collides with an input or already exists.
- Add regression tests covering identical paths, relative path aliases, symbolic links, hard links, and pre-existing output files.
A minimal defensive check for existing files could include:
python import os for input_path in (source_path, target_path): if os.path.exists(output_path) and os.path.samefile(output_path, input_path): raise ValueError("Output path must not refer to a source or target file") with open(output_path, 'x', encoding='utf-8') as f: f.write('\n'.join(lines))Production hardening should prefer descriptor-based exclusive creation to reduce time-of-check to time-of-use race conditions.
- Reject an output path that identifies the same file as either input. For existing paths, use
