T09 · Insecure Skill Coding Practices
- Location
scripts/unexpand.py:3- Finding
Arbitrary Local File Read Through Standard Input
- Content
View full analysis
Vulnerability Details
File Location:
scripts/unexpand.py, line 3
Vulnerability Type: Attacker-controlled file path / arbitrary local file read
Risk Level: MediumVulnerable Code
python print(open(sys.argv[1] if len(sys.argv)>1 else sys.stdin.read()).read().replace(' ', '\t'))Technical Analysis
When no command-line filename is supplied, the expression
sys.stdin.read()is used directly as the argument toopen(). Consequently, standard input is interpreted as a local filesystem path rather than as text to be converted.This behavior contradicts the documented pipeline usage,
cat spaces.txt | unexpand-tool, and creates a file-disclosure primitive wherever an attacker can control standard input and observe the program's output. The script performs no path validation or restriction before opening the selected file.Attack Path
- A service or automation process invokes
scripts/unexpand.pywithout a filename argument. - An attacker controls the data supplied to the process through standard input.
- The attacker submits the path of a sensitive local file, such as an application configuration file.
- The script passes that path to
open()and reads the file with the privileges of its current process. - The file content, with sequences of eight spaces replaced by tabs, is printed to standard output.
- If the output is returned to the attacker, logged in an accessible location, or otherwise exposed, sensitive information is disclosed.
Impact Assessment
An attacker can read any local file for which the executing account has read permission. The vulnerability does not independently grant higher operating-system privileges or permit file modification, but its scope inherits the permissions of the invoking process. If the tool runs under a privileged service account, exposed data may include configuration files, credentials, tokens, source code, or other secrets available to that account.
Exploitation req ...[truncated 146 chars]
- A service or automation process invokes
- Remediation
View remediation
Remediation Suggestions
Handle file arguments and standard input as distinct input sources so that piped content is never treated as a path:
python #!/usr/bin/env python3 import sys if len(sys.argv) > 1: with open(sys.argv[1], encoding="utf-8") as source: content = source.read() else: content = sys.stdin.read() print(content.replace(" ", "\t"), end="")Additionally:
- Use
argparseto validate supported options and reject unexpected arguments. - If this utility is exposed by a service, restrict file access to an explicitly permitted directory and resolve paths before enforcing that boundary.
- Run the tool with the minimum filesystem permissions required.
- Add tests confirming that piped text is transformed directly and cannot select a file.
- Reconcile the implementation with
SKILL.md: the documented-t,-a, and--first-onlyoptions are currently not implemented, and the conversion presently replaces exactly eight spaces globally.
- Use
