T09 · Insecure Skill Coding Practices
- Location
SKILL.md:78- Finding
Predictable Shared Temporary Files Permit Symlink Attacks and Local Information Disclosure
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 78-90
Vulnerability Type: Predictable temporary-file usage
Risk Level: MediumVulnerable 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" fiTechnical Analysis
The workflow writes data to the fixed, globally predictable paths
/tmp/env_defined.txtand/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
/tmpis 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'sumask.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
- A local attacker predicts that the victim will run Env Doctor.
- The attack ...[truncated 1658 chars]
- Remediation
View 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:
- Create a private temporary directory using
mktemp -d. - Set
umask 077before creating files. - Register a cleanup trap.
- Quote every generated path.
- Fail immediately if secure temporary-directory creation fails.
- Do not use fixed filenames directly under a shared
/tmpdirectory.
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" fiWhere feasible, avoid retaining even environment-variable names beyond the duration required for comparison.
- Create a private temporary directory using
