T09 · Insecure Skill Coding Practices
- Location
SKILL.md:235- Finding
Predictable Temporary Files Permit Symlink Attacks and Form-Content Tampering
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 235–244
Vulnerability Type: Predictable and insecure temporary-file usage
Risk Level: MediumVulnerable Code
bash # Backup first curl -s "https://api.tally.so/forms/{ID}" \ -H "Authorization: Bearer $TALLY_KEY" > /tmp/backup.json # Update curl -s "https://api.tally.so/forms/{ID}" \ -X PATCH \ -H "Authorization: Bearer $TALLY_KEY" \ -H "Content-Type: application/json" \ -d @/tmp/form.jsonTechnical Analysis
The documented commands use the globally predictable paths
/tmp/backup.jsonand/tmp/form.json. On multi-user systems, files in/tmpmay be created, replaced, or linked by another local user before the commands execute.Shell output redirection follows symbolic links. If an attacker creates
/tmp/backup.jsonas a symbolic link to another file writable by the victim, the backup command can overwrite that target with the API response. The backup may also contain sensitive form configuration or respondent-related information and could remain accessible if its permissions are affected by an unsafe process umask.The update operation reads its request body directly from the fixed
/tmp/form.jsonpath without verifying file ownership, permissions, type, or integrity. A local attacker able to create or replace that file can cause attacker-controlled form content to be submitted using the victim's authenticated Tally API credentials.Attack Path
Backup symlink attack:
- A local attacker predicts that the victim will execute the documented command.
- The attacker creates
/tmp/backup.jsonas a symbolic link to a file writable by the victim. - The victim runs the backup command.
- Shell redirection follows the symbolic link and overwrites the target with the Tally API response.
- Depending on the selected target, this can corrupt user-owned files or alter user-level configuration.
**Update-c ...[truncated 1420 chars]
- Remediation
View remediation
Remediation Suggestions
Create a private temporary directory with an unpredictable name, enforce restrictive permissions, and remove it automatically:
bash set -euo pipefail umask 077 tmp_dir="$(mktemp -d)" trap 'rm -rf -- "$tmp_dir"' EXIT backup_file="$tmp_dir/backup.json" form_file="$tmp_dir/form.json" curl --fail --silent --show-error \ "https://api.tally.so/forms/{ID}" \ -H "Authorization: Bearer $TALLY_KEY" \ --output "$backup_file" # Create or securely copy the intended update into "$form_file". # Validate its ownership, regular-file status, permissions, and JSON structure. test -f "$form_file" && test ! -L "$form_file" jq empty "$form_file" curl --fail --silent --show-error \ "https://api.tally.so/forms/{ID}" \ -X PATCH \ -H "Authorization: Bearer $TALLY_KEY" \ -H "Content-Type: application/json" \ --data-binary "@$form_file"Additional hardening measures should include:
- Never use fixed filenames in shared temporary directories.
- Verify that update input is a regular file, not a symbolic link.
- Ensure the executing user owns the input file and that it is not writable by other users.
- Validate the JSON schema and expected form identifier before submission.
- Use
curl --fail --silent --show-errorso HTTP and transport failures are not silently treated as success. - Store backups in a protected, user-controlled directory if they must persist.
- Apply least privilege to the Tally API key and rotate it if unauthorized form changes are suspected.
