Back to skill

Security audit

Respond Pr Feedback

Security checks for vulnerabilities and agentic risk

Overview

This skill is a straightforward GitHub PR feedback responder with disclosed posting and thread-resolution behavior, though its temporary file example should be handled carefully.

Before installing, be aware that invoking this skill can post replies and resolve GitHub PR review threads using your gh login. Use --pr to avoid acting on the wrong PR and --no-resolve if you want manual control over thread resolution. Consider replacing the fixed /tmp jq file with mktemp in practice.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
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: Medium

Vulnerable 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
})
JQEOF
bash
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.jq

Technical 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.jq command 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 Practices because 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 as umask 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.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep

Static analysis

No suspicious patterns detected.