T09 · Insecure Skill Coding Practices
Warning
- Location
- SKILL.md:78
- Finding
- Predictable Shared Temporary Files Permit Symlink Attacks and Local Information Disclosure## Vulnerability Details **File Location**: `SKILL.md`, lines 78-90 **Vulnerability Type**: Predictable temporary-file usage **Risk Level**: Medium ### Vulnerable Code ```bash # Parse current .env (if exists) if [ -f .env ]; then grep -v '^#' .env | grep '=' | cut -d= -f1 | sort -u > /tmp/env_defined.txt echo "Found $(wc -l < /tmp/env_defined.txt) defined vars" else echo "No .env file found" fi # Check for .env.example if [ -f .env.example ]; then grep -v '^#' .env.example | grep '=' | cut -d= -f1 | sort -u > /tmp/env_example.txt echo "Found $(wc -l < /tmp/env_example.txt) vars in .env.example" fi ``` ### Technical Analysis The workflow writes data to the fixed, globally predictable paths `/tmp/env_defined.txt` and `/tmp/env_example.txt`. It does not securely create these files, verify their ownership or type, apply restrictive permissions, or remove them after use. On systems where `/tmp` is shared among users, an attacker can pre-create either path as a symbolic link. Shell output redirection follows symbolic links, so executing the documented commands can truncate and overwrite another file to which the victim process has write access. This is a time-of-check/time-of-use and unsafe temporary-file vulnerability. The generated files contain environment-variable names rather than their values. Consequently, the code does not directly copy secret values into `/tmp`. However, variable names can still disclose service providers, authentication mechanisms, infrastructure components, and other project configuration details. Their readability depends on the executing process's `umask`. These shared temporary files are not necessary for the Skill's declared functionality. Comparisons can be performed without persistent temporary files, or with files held inside a securely created private directory. ### Attack Path 1. A local attacker predicts that the victim will run Env Doctor. 2. The attack ...[truncated 1658 chars]
- Remediation
- ## Remediation Suggestions Prefer eliminating temporary files and comparing generated lists through pipelines, process substitution, or in-memory Agent state. If temporary files are required: 1. Create a private temporary directory using `mktemp -d`. 2. Set `umask 077` before creating files. 3. Register a cleanup trap. 4. Quote every generated path. 5. Fail immediately if secure temporary-directory creation fails. 6. Do not use fixed filenames directly under a shared `/tmp` directory. Example hardened pattern: ```bash umask 077 tmp_dir="$(mktemp -d "${TMPDIR:-/tmp}/env-doctor.XXXXXX")" || { echo "Failed to create a secure temporary directory" >&2 exit 1 } trap 'rm -rf -- "$tmp_dir"' EXIT HUP INT TERM if [ -f .env ]; then grep -v '^#' .env | grep '=' | cut -d= -f1 | sort -u > "$tmp_dir/env_defined.txt" echo "Found $(wc -l < "$tmp_dir/env_defined.txt") defined vars" else echo "No .env file found" fi if [ -f .env.example ]; then grep -v '^#' .env.example | grep '=' | cut -d= -f1 | sort -u > "$tmp_dir/env_example.txt" echo "Found $(wc -l < "$tmp_dir/env_example.txt") vars in .env.example" fi ``` Where feasible, avoid retaining even environment-variable names beyond the duration required for comparison.
