Back to skill

Security audit

Pr Triage

Security checks for vulnerabilities and agentic risk

Overview

This PR triage skill is mostly coherent, but it can use an unintended GitHub account and documents optional repository write actions, so users should review it before installing.

Install only if you are comfortable with the skill using your local GitHub CLI authentication. Prefer running it in a constrained environment or updating it to preserve caller-provided GH_TOKEN/GITHUB_TOKEN values, and treat commenting or labeling PRs as separate explicit write actions requiring confirmation.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/triage.py:20
Finding
Forced Removal of Caller-Provided GitHub Tokens Can Cause Privileged Credential Fallback<![CDATA[ ## Vulnerability Details **File Location**: `scripts/triage.py:20-27`; also prescribed by `SKILL.md:26-29`, `SKILL.md:36-41`, and `SKILL.md:193-198` **Vulnerability Type**: Authentication context confusion and violation of least privilege **Risk Level**: Medium ### Vulnerable Code From `scripts/triage.py:20-27`: ```python def run_gh(args: list[str]) -> str: """Run gh CLI command with token env cleared.""" env_prefix = ["env", "-u", "GH_TOKEN", "-u", "GITHUB_TOKEN"] result = subprocess.run( env_prefix + ["gh"] + args, capture_output=True, text=True, ) ``` The corresponding mandatory instruction in `SKILL.md:26-29` is: ```bash **ALWAYS use this pattern for ALL gh commands:** ```bash env -u GH_TOKEN -u GITHUB_TOKEN gh <command> ``` ``` The pattern is also applied to the documented write operations in `SKILL.md:193-198`: ```bash env -u GH_TOKEN -u GITHUB_TOKEN gh pr comment <NUMBER> --body "This PR appears to duplicate #XXX. Please coordinate with the other author or close if redundant." ``` ```bash env -u GH_TOKEN -u GITHUB_TOKEN gh pr edit <NUMBER> --add-label "duplicate" env -u GH_TOKEN -u GITHUB_TOKEN gh pr edit <NUMBER> --add-label "needs-review" ``` ### Technical Analysis The Skill unconditionally removes `GH_TOKEN` and `GITHUB_TOKEN` before every GitHub CLI invocation. These environment variables are commonly used to provide a deliberately scoped, invocation-specific credential. Removing them causes `gh` to use another available authentication source, typically a credential previously stored by `gh auth login`. This creates authentication-context confusion: the caller may expect the operation to use a restricted token, but the Skill silently substitutes the locally stored GitHub identity. That identity may have access to private repositories or broader write privileges. The behavior is not necessary for the declared PR-triage functionality. Reading pull-request metadata only requires a suitably sc ...[truncated 2362 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the forced token deletion and invoke GitHub CLI directly: ```python result = subprocess.run( ["gh"] + args, capture_output=True, text=True, check=False, ) ``` 2. Preserve caller-provided `GH_TOKEN` and `GITHUB_TOKEN` values. If authentication isolation is required, accept an explicit credential or profile option instead of silently switching identities. 3. Verify the selected identity before accessing repository data, for example with `gh auth status`, and display the hostname and account to the caller. 4. Document the minimum required token permissions: - Read-only repository and pull-request metadata for normal triage. - Separate, explicitly approved write permissions only for comment or label actions. 5. Separate read and write execution paths. Require explicit confirmation immediately before any mutation, and verify that the selected identity and target repository match the user's request. 6. Fail closed when no explicitly approved authentication source is available rather than falling back silently to a stored credential. 7. Update every example and the “ALWAYS use this pattern” instruction in `SKILL.md` so it no longer mandates removal of environment-provided tokens. ]]>
Vulnerability Patterns
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • 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 (4)

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill invokes shell commands and can write output files, but the manifest does not declare any tool scope or permission boundaries. That creates an authorization gap where an agent/runtime may permit broader capabilities than users expect, increasing the risk of command execution or filesystem writes without clear consent controls.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The skill is presented as triage/reporting, but it also documents repository-modifying actions like commenting on PRs and adding labels. This scope drift is dangerous because users or orchestrators may invoke a supposedly read-focused skill in contexts where write actions are not expected, leading to unintended modification of repository state.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The boundary section says the skill will not comment without an explicit flag, while an earlier optional-actions section describes commenting behavior. This inconsistency can cause policy and implementation confusion, making it easier for an agent or operator to mis-handle when repository write actions are allowed.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def run_gh(args: list[str]) -> str:
    """Run gh CLI command with token env cleared."""
    env_prefix = ["env", "-u", "GH_TOKEN", "-u", "GITHUB_TOKEN"]
    result = subprocess.run(
        env_prefix + ["gh"] + args,
        capture_output=True,
        text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Static analysis

No suspicious patterns detected.