Back to skill

Security audit

Git Hub CLI省Token只读工具集

Security checks for vulnerabilities and agentic risk

Overview

This read-only GitHub helper is mostly coherent, but it uses GitHub credentials, broad activation triggers, automatic login guidance, and an unsafe temporary cache that may expose private repository data.

Install only if you are comfortable letting the agent make read-only GitHub queries with your configured GitHub credentials. Prefer least-privilege tokens, avoid using it for highly sensitive private repositories on shared machines, and consider removing automatic login plus hardening or disabling the temporary cache before use.

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:40
Finding

Predictable and Insecure Temporary Cache Files

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 40–42
Vulnerability Type: Unsafe temporary file handling
Risk Level: Medium

Vulnerable Code

bash
local f="/tmp/gh_${h}.json"
local mtime; mtime=$(stat -c %Y "$f" 2>/dev/null || stat -f %m "$f" 2>/dev/null || echo 0)
if [ -f "$f" ] && [ $(( $(date +%s) - mtime )) -lt 1800 ]; then cat "$f"; else gh "$@" | tee "$f"; fi

The corresponding PowerShell implementation at lines 87–91 has the same general weakness:

powershell
$f = Join-Path $env:TEMP "gh_$key.json"
if ((Test-Path $f) -and ((Get-Date) - (Get-Item $f).LastWriteTime).TotalMinutes -lt 30) {
  Get-Content $f -Raw
} else {
  $r = gh @args | Out-String; Set-Content -Path $f -Value $r; $r
}

Technical Analysis

The cache filename is derived deterministically from the GitHub CLI arguments and is placed in a shared temporary directory. The implementation neither securely creates the cache file nor verifies its ownership, type, or link status before reading or writing it. It also does not explicitly enforce restrictive file permissions.

In the Bash implementation, tee "$f" follows symbolic links. A local attacker who can derive the cache key may pre-create /tmp/gh_${h}.json as a symbolic link to another file writable by the Agent process. A subsequent cache miss would make tee follow that link and overwrite the target with the GitHub response.

The cache can contain responses from authenticated queries against private repositories. Depending on the process umask and temporary-directory controls, those responses may be readable by other local users. A pre-created fresh cache entry can also cause the function to return attacker-controlled content instead of querying GitHub. The PowerShell variant similarly uses a predictable path without explicit user-only ACLs or reparse-point validation.

Attack Path

  1. A local attacker observes or predicts the arguments supplied ...[truncated 1635 chars]
Remediation
View remediation

Remediation Suggestions

  • Store cache data in a private, per-user directory rather than directly in shared /tmp; create that directory with mode 0700.
  • Create cache files atomically with mode 0600, independent of the caller's umask.
  • Reject symbolic links and other unexpected file types, and verify that existing cache files are owned by the current user.
  • Write responses to a securely created temporary file in the same private directory, then atomically rename it to the final cache path.
  • Use an exclusive-create operation to prevent pre-creation races. Where available, use descriptor-relative APIs and no-follow semantics.
  • On PowerShell, apply an ACL granting access only to the current user and reject reparse points before reading, writing, or replacing cache entries.
  • Treat cached GitHub output as untrusted input even after filesystem hardening; validate its expected JSON structure before further Agent processing.
  • Avoid caching sensitive private-repository responses unless caching is necessary, and remove cache entries when the session ends or authentication context changes.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (12)

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger list is broad enough to activate on common GitHub-related conversation terms, which can cause the skill to engage unexpectedly outside the user's intent. In an authenticated environment, unintended activation can lead to unnecessary repository queries and disclosure of private metadata into the conversation context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The instruction 全篇使用 O/R 代替 owner/repo imposes a fixed terminology/style requirement across the document, and the skill otherwise presents its instructions in Chinese without offering a language or locale choice. This creates a natural-language policy concern because the skill appears to force a specific language/terminology convention without documenting user opt-in or a justified locale restriction.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
91% confidence
Finding

The curl fallback transmits an authorization token to an external network endpoint outside the declared gh-only control path. Even though the endpoint is GitHub, bypassing the CLI's expected wrapper functions and guardrails increases the risk of credential misuse, logging exposure, and policy evasion in sandboxed environments.

Content

Scanner excerpt · SKILL.md (reported line 224)May include surrounding context.

bash
curl -s --max-time 30 -H "Authorization: token $GITHUB_TOKEN" \
  -H "Accept: application/vnd.github.v3+json" \
  "https://api.github.com/repos/O/R/contents/README.md" \
  | jq -c '.content | @base64d'

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 239)May include surrounding context.

md
| T4 | 读文件解码 | `gh_read cli/cli README.md \| grep -q 'GitHub CLI'` | exit 0 |
| T5 | 目录树限深 | `gh_tree cli/cli 2 \| head -1 \| awk -F/ '{exit !(NF<=2)}'` | exit 0 |
| T6 | 动态截断 | `TOKEN_QUOTA=400 truncate_by_quota cli/cli README.md \| wc -l` | `49` 或 `50` |
| T7 | 降级 curl | `curl -s --max-time 5 https://api.github.com/rate_limit \| jq -e '.resources.core'` | exit 0 |
| T8 | PowerShell | `pwsh -NoProfile -Command "gh --version"` | 含 `gh version` |
| T9 | 函数加载 | `type gh_timed gh_cached retry gh_read gh_tree truncate_by_quota gh_default_branch >/dev/null 2>&1` | exit 0 |

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 252)May include surrounding context.

md
| T4 | 读文件解码 | `gh_read cli/cli README.md \| grep -q 'GitHub CLI'` | exit 0 |
| T5 | 目录树限深 | `gh_tree cli/cli 2 \| head -1 \| awk -F/ '{exit !(NF<=2)}'` | exit 0 |
| T6 | 动态截断 | `TOKEN_QUOTA=400 truncate_by_quota cli/cli README.md \| wc -l` | `49` 或 `50` |
| T7 | 降级 curl | `curl -s --max-time 5 https://api.github.com/rate_limit \| jq -e '.resources.core'` | exit 0 |
| T8 | PowerShell | `pwsh -NoProfile -Command "gh --version"` | 含 `gh version` |
| T9 | 函数加载 | `type gh_timed gh_cached retry gh_read gh_tree truncate_by_quota gh_default_branch >/dev/null 2>&1` | exit 0 |

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The file content is written as a Chinese-only skill description ('AI Agent专用...') with no indication that other languages are supported or that the user can choose a preferred language. This creates a natural-language locale policy concern because it implicitly constrains the skill to a specific language without documented opt-in or justification.

Content

No source excerpt is available for this finding.

Overly Broad Trigger

Low
Category
Trigger Abuse
Confidence
88% confidence
Finding

The trigger gh is extremely short and likely to match unintentionally, causing the skill to activate in contexts where the user did not request GitHub access. In authenticated agent settings, accidental invocation can still expose repository metadata or consume rate limits without clear user intent.

Content

No source excerpt is available for this finding.

Overly Broad Trigger

Low
Category
Trigger Abuse
Confidence
84% confidence
Finding

The trigger pr is ambiguous and common in normal conversation, making unintended skill activation likely. Unexpected activation is risky because the skill is designed to query live GitHub state and may surface repository information the user did not mean to request.

Content

No source excerpt is available for this finding.

Overly Broad Trigger

Low
Category
Trigger Abuse
Confidence
84% confidence
Finding

The trigger ci is also short and contextually broad, so it may fire on unrelated discussions about continuous integration or abbreviations in other domains. This raises the chance of unnecessary authenticated GitHub access and context pollution.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
87% confidence
Finding

The instruction to run gh auth status || gh auth login can trigger an interactive authentication flow and encourage users or agents to obtain credentials unnecessarily for a nominally read-only skill. In constrained agent environments, this expands credential exposure and may lead to broader scopes being granted than needed.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The note claims gh_default_branch is 'already encapsulated' with a 'main→master→API' fallback strategy. But both bash and PowerShell implementations simply call 'repos/$1' and return '.default_branch // "main"', with no probing of main or master branches. This is an active contradiction between the documentation and the actual function behavior.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The manifest description says this is a 'GitHub CLI read-only Skill', which implies operations are performed through the GitHub CLI. However, the fallback section explicitly uses curl with a GitHub token to call the GitHub REST API directly. While still read-only, this behavior exceeds the plain CLI-only description and creates a description-versus-implementation mismatch.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.