Back to skill

Security audit

review-github-pr

Security checks for vulnerabilities and agentic risk

Overview

This PR-review skill mostly matches its stated purpose, but it needs review because one posting step uses a predictable temporary file that could let local tampering change an authenticated GitHub review.

Use this only if you are comfortable giving the agent access to the target repository and your active GitHub CLI credentials. Before posting reviews, replace the fixed /tmp/pr-review.json workflow with mktemp or stdin piping, verify the final repository and review action, and remove temporary payloads after submission.

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:220
Finding
Predictable temporary review file permits symlink overwrite and review-payload tampering## Vulnerability Details **File Location**: `SKILL.md:220-242` **Vulnerability Type**: Predictable unsafe temporary file **Risk Level**: Medium ### Vulnerable Code ```bash cat > /tmp/pr-review.json <<'EOF' { "event": "REQUEST_CHANGES", "body": "1 critical, 1 minor - details inline on the diff.", "comments": [ { "path": "src/main.rs", "line": 1653, "side": "RIGHT", "body": "[Correctness] `fmt::layer()` defaults to stdout, moving all tracing output onto the JSON-RPC channel.\n\n```suggestion\n .with(fmt::layer().with_writer(std::io::stderr))\n```" }, { "path": "src/main.rs", "start_line": 1651, "line": 1654, "side": "RIGHT", "body": "[Convention] The stderr choice deserves a WHY comment - it is the only thing keeping stdout clean for JSON-RPC." } ] } EOF gh api repos/{owner}/{repo}/pulls/<number>/reviews --input /tmp/pr-review.json ``` ### Technical Analysis The skill instructs the agent to create a sensitive API request payload at the fixed, globally predictable path `/tmp/pr-review.json`. Shell output redirection normally follows symbolic links and does not create the file atomically with exclusive ownership checks. A local attacker able to manipulate that path may exploit two distinct time-of-check/time-of-use opportunities: 1. Before redirection, the attacker can place a symbolic link at `/tmp/pr-review.json`. The shell may then truncate and overwrite the link target with the review JSON. 2. After the heredoc finishes but before `gh api` opens the file, the attacker can replace or alter the predictable file. The GitHub CLI would then transmit attacker-controlled review content using the victim's authenticated GitHub credentials. Common Linux protections such as `fs.protected_symlinks` and sticky-directory ownership restrictions can reduce cross-user exploitation, but they are platform-d ...[truncated 2693 chars]
Remediation
## Remediation Suggestions Replace the fixed filename with a securely and atomically created temporary file, restrict its permissions, pass the exact generated path to `gh`, and guarantee cleanup: ```bash review_file="$(mktemp "${TMPDIR:-/tmp}/pr-review.XXXXXXXX.json")" || exit 1 chmod 600 "$review_file" trap 'rm -f -- "$review_file"' EXIT HUP INT TERM cat > "$review_file" <<'EOF' { "event": "REQUEST_CHANGES", "body": "1 critical, 1 minor - details inline on the diff.", "comments": [] } EOF gh api "repos/{owner}/{repo}/pulls/<number>/reviews" --input "$review_file" ``` Additional hardening should include: - Prefer piping the generated payload directly to `gh api --input -` if supported, eliminating the temporary file. - Generate JSON with a structured serializer such as `jq` rather than interpolating untrusted strings into a heredoc. - Keep the existing explicit user-confirmation requirement before transmission. - Validate the final repository, pull-request number, review event, and payload summary immediately before submission. - Avoid printing tokens or authenticated command environments in logs. - Ensure cleanup occurs on successful completion, errors, and interruption. - If a temporary file must be reopened, verify that it remains a regular file owned by the current user and has not been replaced before submission.
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description is for an operational PR-review skill that analyzes an actual GitHub pull request and drafts review comments. The supplied code does not review a PR at all. Instead, it is a test fixture setup script used to simulate a clean PR scenario: it initializes a repository, creates base and feature-branch code, computes a diff, installs a mock `gh` command, and outputs instructions for running the fixture. This is a materially different primary purpose and includes undeclared capabilities related to repository creation, branch manipulation, and command mocking.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description says the skill reviews GitHub pull requests end to end. However, this code does not implement review logic, run checks, perform multi-agent analysis, validate findings, or draft inline comments. Its actual purpose is to build a local fixture repository with intentional bugs and conventions violations for testing such a reviewer. The mock gh CLI only emits canned responses and does not represent genuine PR review behavior. This is a materially different primary purpose and includes undeclared repository/file-system setup capabilities.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description is for a PR review skill that analyzes an existing GitHub pull request. This code chunk instead is a test/setup script for an evaluation fixture. Its primary purpose is to create a sample repository with intentional efficiency/design issues and mock out gh responses. While it tangentially relates to PR review testing, it does not itself fetch a real PR, run review checks, perform three-agent analysis, validate findings, or draft comments. The behavior is materially different from the declared purpose and includes undeclared file-system and git-repository setup capabilities.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill invokes shell and network-capable tools (`gh`, `git`, cloning, checkout, API posting) but does not declare any explicit tool scope such as `permissions` or `allowed-tools`. That creates an authorization gap where a host agent may grant broader capabilities than reviewers expect, increasing the chance of unintended command execution, repo mutation, or outbound requests when handling untrusted PR content.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
http.Error(w, "internal error", http.StatusInternalServerError)
		return
	}
	// Bug: ticket can be nil if not found, but we access .Title without checking
	response := map[string]interface{}{
		"id":       ticket.ID,
		"title":    ticket.Title,
Confidence
75% confidence
Finding
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This setup script immediately creates a temporary repository, changes directories, initializes git, and later writes many files and an executable helper script. Although comments describe what the fixture does, there is no user-facing warning, prompt, or explicit disclosure in the script output before these state-changing operations begin.

Scope Creep

Low
Category
Excessive Agency
Content
permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation source, and
configuration files.

"Object" form shall mean any form resulting from mechanical transformation or
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Scope Creep

Low
Category
Excessive Agency
Content
permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation source, and
configuration files.

"Object" form shall mean any form resulting from mechanical transformation or
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Scope Creep

Low
Category
Excessive Agency
Content
permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation source, and
configuration files.

"Object" form shall mean any form resulting from mechanical transformation or
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Scope Creep

Low
Category
Excessive Agency
Content
permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation source, and
configuration files.

"Object" form shall mean any form resulting from mechanical transformation or
Confidence
70% confidence
Finding
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Missing User Warnings

Low
Confidence
86% confidence
Finding
This code file creates a temporary repository, writes multiple files with heredocs, initializes and commits a Git repository, and checks out branches. While comments describe what the script does for developers reading the file, there is no runtime disclosure, prompt, or other user-facing warning before these state-changing operations execute.

Static analysis

No suspicious patterns detected.