T09 · Insecure Skill Coding Practices
- Location
SKILL.md:63- Finding
Predictable Temporary File Allows Symlink-Based File Overwrite
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md, lines 63–92
Vulnerability Type: Insecure predictable temporary file
Risk Level: MediumVulnerable Code
bash cat > /tmp/unreplied_comments.jq << 'JQEOF' add // [] | # Root comments from reviewers (not replies, not PR author, not current user) [.[] | select( .in_reply_to_id == null and .user.login != $pr_author and .user.login != $current_user )] as $roots | # IDs that current user has already replied to [.[] | select(.user.login == $current_user) | .in_reply_to_id] as $replied | # Filter to unreplied only $roots | map(select(. as $c | $replied | index($c.id) == null)) | # Dedup: group by path + line + reviewer, pick newest per group group_by({ p: .path, l: (.line // .original_line), u: .user.login }) | map(sort_by(.created_at) | last) | # Output needed fields map({ id, user: .user.login, path, line_display: ( .line as $end | .start_line as $start | if $start and $start != $end then "\($start)-\($end)" else "\($end // .original_line)" end ), body }) JQEOFbash gh api --paginate "repos/$OWNER/$REPO/pulls/$PR_NUMBER/comments" | \ jq -s --arg pr_author "$PR_AUTHOR" --arg current_user "$CURRENT_USER" \ -f /tmp/unreplied_comments.jqTechnical Analysis
The Skill writes its jq filter to the fixed, globally predictable path
/tmp/unreplied_comments.jq. Shell output redirection opens this path for truncation without securely creating the file, verifying its ownership, or rejecting symbolic links.On a shared system, another local user can create that path as a symbolic link to a file writable by the user who later invokes the Skill. When the documented
cat > /tmp/unreplied_comments.jqcommand runs, the shell follows the symbolic link and truncates and replaces the linked target with the jq program.The issue is classified as
T09: Insecure Skill Coding Practicesbecause it results from unsafe temporary-file handling in the Skill instru ...[truncated 1510 chars]- Remediation
View remediation
Remediation Suggestions
Create a unique temporary file securely with
mktemp, restrict its permissions, reference the generated path consistently, and remove it when execution ends:bash JQ_FILTER=$(mktemp "${TMPDIR:-/tmp}/unreplied_comments.XXXXXX.jq") || exit 1 chmod 600 "$JQ_FILTER" trap 'rm -f "$JQ_FILTER"' EXIT cat > "$JQ_FILTER" << 'JQEOF' add // [] | # Existing jq filter content JQEOF gh api --paginate "repos/$OWNER/$REPO/pulls/$PR_NUMBER/comments" | \ jq -s --arg pr_author "$PR_AUTHOR" --arg current_user "$CURRENT_USER" \ -f "$JQ_FILTER"Additionally:
- Fail immediately if secure temporary-file creation fails.
- Quote every reference to the generated temporary path.
- Use a restrictive
umask, such asumask 077, before creating temporary artifacts. - Retain the cleanup trap so the temporary file is removed on normal completion and common error paths.
- Do not revert to a fixed filename in a shared temporary directory.
