T09 · Insecure Skill Coding Practices
- Location
scripts/main.py:635- Finding
Unrestricted User-Controlled File Read
- Content
View full analysis
Vulnerability Details
File Location:
scripts/main.py:635-642
Vulnerability Type: Arbitrary file read through an unrestricted input path
Risk Level: MediumVulnerable Code:
python if args.review: if not args.input: print("Error: --input required for review mode", file=sys.stderr) sys.exit(1) content = Path(args.input).read_text() result = assistant.review_proposal(content)Technical Analysis
The
--inputargument is controlled by the caller and is passed directly toPath.read_text()without path normalization, workspace confinement, symlink validation, regular-file validation, or a file-size limit. Absolute paths and traversal sequences such as../are therefore accepted.This violates least-privilege expectations for a proposal-reviewing Skill, which should only access proposal files inside an authorized workspace. It also conflicts with the path-validation and workspace-restriction objectives documented in
SKILL.md.The review report does not reproduce the complete input, which limits direct disclosure. Nevertheless, processing a sensitive file can reveal derived information such as its word count, estimated page count, detected section names, keywords, and checklist results. Large or special files may also cause resource exhaustion or unhandled exceptions.
Attack Path
- An attacker persuades the user or Agent to review a path outside the authorized workspace.
- The Skill is invoked with an argument such as:
bash python3 scripts/main.py --review --input ../../sensitive-file --output report.md Path(args.input).read_text()resolves and reads the external file using the operating-system permissions of the Skill process.- The review logic analyzes the file and exposes derived metadata in the generated report.
- If the selected file is very large, the unrestricted read may also consume excessive memory and CPU.
...[truncated 511 chars]
- Remediation
View remediation
Remediation Suggestions
- Define an explicit workspace root and resolve the supplied path before use:
python workspace = Path.cwd().resolve() input_path = Path(args.input).resolve(strict=True) if not input_path.is_relative_to(workspace): raise ValueError("Input file must be inside the authorized workspace") - Reject symbolic links when they are not explicitly required, and verify that the target is a regular file.
- Permit only expected proposal file types where practical.
- Check file size before reading and enforce a reasonable maximum.
- Specify and safely handle text encoding and decoding errors.
- Catch filesystem exceptions and return sanitized errors without exposing unnecessary host details.
- Apply the same validation in both command-line and library-facing interfaces.
- Define an explicit workspace root and resolve the supplied path before use:
