T09 · Insecure Skill Coding Practices
- Location
SKILL.md:71- Finding
Predictable Temporary Files Permit Symlink-Based File Overwrite
- Content
View full analysis
/tmp/zoho_search.json { "path_variables": {"module": "Contacts"}, "query_params": {"criteria": "(Last_Name:equals:Smith)"} } EOF mcporter call "$ZOHO_MCP_URL.ZohoCRM_searchRecords" --args "$(< /tmp/zoho_search.json)" ``` `SKILL.md:82-87`: ```bash cat << 'EOF' > /tmp/zoho_record.json { "path_variables": {"module": "Accounts", "recordID": "1234567890"} } EOF mcporter call "$ZOHO_MCP_URL.ZohoCRM_getRecord" --args "$(< /tmp/zoho_record.json)" ``` `SKILL.md:92-97`: ```bash cat << 'EOF' > /tmp/zoho_coql.json { "body": {"select_query": "SELECT Id, Account_Name, Website FROM Accounts WHERE Website != '' ORDER BY Account_Name LIMIT 50"} } EOF mcporter call "$ZOHO_MCP_URL.ZohoCRM_executeCOQLQuery" --args "$(< /tmp/zoho_coql.json)" ``` `SKILL.md:190-197`: ```bash cat << 'EOF' > /tmp/args.json { "path_variables": {"module": "Contacts"}, "query_params": {"criteria": "(Email:equals:test@example.com)"} } EOF mcporter call "$ZOHO_MCP_URL.ZohoCRM_searchRecords" --args "$(< /tmp/args.json)" ``` Equivalent vulnerable examples appear in `README.md:80-86`, `README.md:92-97`, `README.md:103-108`, and `README.md:177-183`. ### Technical Analysis The shell redirection operator (`>`) opens an existing destination with truncation enabled and follows symbolic links. The documented filenames are fixed and predictable within the shared `/tmp` namespace. The commands do not: - Create files atomically with exclusive semantics. - Verify file ownership or re ...[truncated 2158 chars]- Remediation
View remediation
"$args_file" <<'EOF' { "path_variables": {"module": "Contacts"}, "query_params": {"criteria": "(Last_Name:equals:Smith)"} } EOF mcporter call "$ZOHO_MCP_URL.ZohoCRM_searchRecords" \ --args "$(< "$args_file")" ``` For workflows requiring several files, create a private temporary directory: ```bash tmp_dir="$(mktemp -d)" || exit 1 chmod 700 "$tmp_dir" trap 'rm -rf -- "$tmp_dir"' EXIT HUP INT TERM args_file="$tmp_dir/args.json" ``` Additional hardening measures: 1. Never recommend predictable filenames in shared temporary directories. 2. Quote every generated path. 3. Apply permissions of `0600` to files containing request data. 4. Register cleanup immediately after successful temporary-file creation. 5. Avoid running these examples as a privileged user. 6. Where practical, use the bundled Python helpers or pass serialized JSON directly as an argument, eliminating temporary files entirely. 7. Update all duplicate examples in both documentation files so users are not directed back to an unsafe pattern. ]]>
