Back to skill

Security audit

Github

Security checks for vulnerabilities and agentic risk

Overview

This is a legitimate GitHub automation skill, but it can change repositories and GitHub login state with weak safeguards and has implementation flaws that users should review before installing.

Install only if you trust this skill to act on your GitHub repositories with your current gh identity. Use dry-run modes where available, avoid untrusted account aliases or notification content, review branch cleanup targets before running, and be aware that account add/switch may log out your current GitHub CLI session and notifications may send repo metadata to external chat services.

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 (2)

T09 · Insecure Skill Coding Practices

Error
Location
github-accounts.sh:113
Finding
Path Traversal in GitHub Account Alias Allows Arbitrary JSON File Overwrite or Deletion## Vulnerability Details **File Location**: `github-accounts.sh`, lines 113-143, 209-250, and 269-286 **Vulnerability Type**: Path traversal through an unvalidated filename component **Risk Level**: High ### Vulnerable Code Account switching constructs a path directly from the caller-controlled alias: ```bash local config_file="$ACCOUNTS_DIR/${alias}.json" if [[ ! -f "$config_file" ]]; then echo -e "${YELLOW}⚠️ 账户配置不存在,需要重新认证${NC}" echo "" # 保存当前账户 local current=$(get_current_account) echo "$current" > "$ACCOUNTS_DIR/.backup_current" # 退出当前认证 gh auth logout -y 2>/dev/null || true # 重新认证 gh auth login --hostname github.com --git-protocol https # 保存配置 local user=$(gh api user --jq .login 2>/dev/null) local email=$(gh api user --jq .email 2>/dev/null || echo "private") cat > "$config_file" << EOF { "alias": "${alias}", "username": "${user}", "email": "${email}", "hostname": "github.com", "protocol": "https", "authedAt": "$(date -Iseconds)", "scopes": ["repo", "user", "workflow"] } EOF ``` The same unsafe construction is used when adding an account: ```bash local config_file="$ACCOUNTS_DIR/${alias}.json" if [[ -f "$config_file" ]]; then echo -e "${YELLOW}⚠️ 账户 ${alias} 已存在${NC}" echo "" echo -e "${CYAN}当前配置:${NC}" cat "$config_file" echo "" read -p "是否覆盖?(y/N) " -n 1 -r echo "" if [[ ! $REPLY =~ ^[Yy]$ ]]; then exit 0 fi fi # 保存当前账户 local current=$(get_current_account) echo "$current" > "$ACCOUNTS_DIR/.backup_current" # 退出当前认证 gh auth logout -y 2>/dev/null || true # 交互式认证 echo -e "${YELLOW}📝 开始认证流程...${NC}" echo "" gh auth login --hostname github.com --git-protocol https # 获取用户信息 local user=$(gh api user --jq .login 2>/dev/null) local email=$(gh api user --jq .email 2>/dev/null || echo "private") # 保存配置 cat > "$config_f ...[truncated 3576 chars]
Remediation
## Remediation Suggestions 1. Enforce a strict allowlist for aliases before constructing any path: ```bash validate_alias() { local alias="$1" if [[ ! "$alias" =~ ^[A-Za-z0-9_-]+$ ]]; then echo "Invalid account alias" >&amp;2 exit 1 fi } ``` 2. Call `validate_alias "$alias"` in `add_account`, `switch_account`, `remove_account`, and every function that derives a path from an alias. 3. Explicitly reject path separators, `.` and `..` traversal components, control characters, and empty aliases. 4. Canonicalize and verify the destination before writing or deleting: ```bash accounts_root=$(realpath -m "$ACCOUNTS_DIR") config_file=$(realpath -m "$ACCOUNTS_DIR/${alias}.json") case "$config_file" in "$accounts_root"/*.json) ;; *) echo "Resolved path is outside the account directory" >&amp;2 exit 1 ;; esac ``` 5. Create account files atomically using a temporary file inside `$ACCOUNTS_DIR`, set restrictive permissions with `umask 077`, and rename the temporary file only after successful generation and validation. 6. Generate JSON with `jq -n --arg` rather than a heredoc so aliases, usernames, and email addresses are escaped correctly. 7. For deletion, reject symbolic links and verify both the canonical parent directory and expected regular-file type immediately before calling `rm`.

T09 · Insecure Skill Coding Practices

Warning
Location
github-notify.sh:116
Finding
Unescaped Notification Fields Permit JSON Payload Injection## Vulnerability Details **File Location**: `github-notify.sh`, lines 116-129, 151-160, and 205-217 **Vulnerability Type**: JSON injection caused by unsafe string interpolation **Risk Level**: Medium ### Vulnerable Code Discord payload construction: ```bash local payload=$(cat << EOF { "content": "", "embeds": [ { "title": "${title}", "description": "${description}", "color": ${color}, "thumbnail": { "url": "${icon:-https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png}" } } ] } EOF ) ``` DingTalk payload construction: ```bash local payload=$(cat << EOF { "msgtype": "markdown", "markdown": { "title": "${title}", "text": "### ${title}\n${description}\n\n---\n发送时间: $(date '+%Y-%m-%d %H:%M:%S')" } } EOF ) ``` Slack payload construction: ```bash local payload=$(cat << EOF { "attachments": [ { "title": "${title}", "text": "${description}", "color": "${color}", "footer": "GitHub Notifications", "ts": "$(date +%s)" } ] } EOF ) ``` The generated payload is sent directly to the configured webhook: ```bash curl -s -X POST \ -H "Content-Type: application/json" \ -d "$payload" \ "$webhook_url" > /dev/null 2>&amp;1 ``` ### Technical Analysis Notification values derived from command-line arguments or a caller-selected file are interpolated directly into JSON heredocs. The affected fields include the title, description, color, and icon URL. JSON strings require escaping for quotation marks, backslashes, carriage returns, line feeds, and other control characters. Shell quoting around `"$payload"` only preserves the assembled string when invoking `curl`; it does not make the interpolated content valid or safe JSON. For example, a title containing a quotation mark can terminate the intended JSON string. ...[truncated 2927 chars]
Remediation
## Remediation Suggestions 1. Construct JSON with `jq` instead of interpolating values into heredocs. For example: ```bash payload=$(jq -n \ --arg title "$title" \ --arg description "$description" \ --arg icon "${icon:-https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png}" \ --argjson color "$color" \ '{ content: "", embeds: [{ title: $title, description: $description, color: $color, thumbnail: {url: $icon} }] }') ``` 2. Validate Discord colors as decimal integers within the platform-supported range before passing them to `--argjson`: ```bash if [[ ! "$color" =~ ^[0-9]+$ ]] || (( color &lt; 0 || color &gt; 16777215 )); then echo "Invalid Discord color" >&amp;2 exit 1 fi ``` 3. Use `jq -n --arg` for every string in the Discord, DingTalk, and Slack payloads. Do not manually escape JSON with `sed` or string replacement. 4. Validate icon URLs against an explicit `https` policy if arbitrary remote images are not required. 5. Consider restricting or neutralizing mass-mention syntax when notification text can originate from untrusted users. 6. Make HTTP failures visible: ```bash curl --fail-with-body --silent --show-error \ -X POST \ -H "Content-Type: application/json" \ --data-binary "$payload" \ "$webhook_url" ``` 7. Report success only after `curl` returns successfully and the destination provides an acceptable HTTP status.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The documented feature set understates destructive repository actions such as deleting remote branches or modifying PR labels. Users invoking a seemingly general GitHub assistant may not expect destructive mutations, which creates a real risk of accidental data loss or unauthorized repository changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The documented feature set understates destructive repository actions such as deleting remote branches or modifying PR labels. Users invoking a seemingly general GitHub assistant may not expect destructive mutations, which creates a real risk of accidental data loss or unauthorized repository changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The documented feature set understates destructive repository actions such as deleting remote branches or modifying PR labels. Users invoking a seemingly general GitHub assistant may not expect destructive mutations, which creates a real risk of accidental data loss or unauthorized repository changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The documented feature set understates destructive repository actions such as deleting remote branches or modifying PR labels. Users invoking a seemingly general GitHub assistant may not expect destructive mutations, which creates a real risk of accidental data loss or unauthorized repository changes.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
The documented feature set understates destructive repository actions such as deleting remote branches or modifying PR labels. Users invoking a seemingly general GitHub assistant may not expect destructive mutations, which creates a real risk of accidental data loss or unauthorized repository changes.

Lp3

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding
The skill documentation advertises shell-based operational workflows but does not declare any tool scope such as permissions or allowed-tools. In an agent ecosystem, missing scope declarations can cause reviewers or users to underestimate the skill's ability to run local commands and modify repository state, increasing the chance of unsafe execution.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The skill description and all user-facing documentation are presented exclusively in Chinese, with no indication that users can choose another language or that the locale restriction is intentional and justified. This can violate language/locale policy when a specific language is effectively forced without opt-in.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
Force-push and merge operations can overwrite remote history, close PRs, and change repository state in ways that affect collaborators. Documenting these commands without warnings or safeguards makes misuse more likely, especially in an automation skill where users may assume safe defaults.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The documentation instructs users on branch-cleanup operations that can delete branches and alter repository state, but it does not prominently warn about data loss or recommend dry-run/confirmation-first usage. In a GitHub automation context, this increases the likelihood of accidental destructive actions, especially when users rely on one-click cleanup behavior.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The notification feature is documented as sending GitHub event data to Discord, DingTalk, Telegram, and Slack, but there is no privacy or data-handling warning. Repository names, PR titles, authors, issue numbers, and URLs can reveal sensitive internal development information when transmitted to third-party services.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The script calls `gh auth logout -y` during account switching when a config is missing, which forcibly terminates the user's current GitHub CLI session without an explicit warning or confirmation at that moment. In a multi-account helper, this can unexpectedly disrupt authenticated workflows, invalidate the active session for unrelated repositories, and cause accidental operations under a different account after re-login.

Missing User Warnings

Medium
Confidence
98% confidence
Finding
The add-account flow also executes `gh auth logout -y` unconditionally before starting a new login, without a dedicated user warning that their existing GitHub CLI authentication will be removed. This is dangerous because the tool manages a global auth state, so adding one account can silently break current automation, repository access, or push/review operations tied to the previous login.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
This shell script embeds user-facing help text, usage instructions, and status messaging in Chinese only. Under the policy rule, forcing a specific language without user opt-in is a natural-language policy violation unless the locale constraint is clearly documented and justified, which is not present here.

External Transmission

Medium
Category
Data Exfiltration
Content
EOF
)
    
    curl -s -X POST \
        -H "Content-Type: application/json" \
        -d "$payload" \
        "$webhook_url" > /dev/null 2>&1
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
local text=$(printf "%s\n%s" "$title" "$description")
    
    curl -s -X POST \
        "https://api.telegram.org/bot${bot_token}/sendMessage" \
        -d "chat_id=${chat_id}" \
        -d "text=${text}" > /dev/null 2>&1
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
local text=$(printf "%s\n%s" "$title" "$description")
    
    curl -s -X POST \
        "https://api.telegram.org/bot${bot_token}/sendMessage" \
        -d "chat_id=${chat_id}" \
        -d "text=${text}" > /dev/null 2>&1
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The top-level documentation and help text describe the 'conflicts' command as processing conflicting PRs, which implies some operative handling. In reality, the handle_conflicts function only lists PRs with merge conflicts and echoes suggested git commands for a human to run, without performing conflict resolution or updating the PR.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script performs destructive remote branch deletion immediately via `git push origin --delete` without any interactive confirmation, while the help text advertises a `--yes` flag that implies confirmation should normally exist. In a repository-maintenance skill, this increases the risk of accidental deletion of important branches, especially when branch names come from GitHub PR metadata and the tool is positioned as an automation helper.

Missing User Warnings

Medium
Confidence
83% confidence
Finding
The help text advertises a `-f, --force` option, which implies a potentially destructive git push mode that can overwrite remote history, but there is no corresponding warning about that risk anywhere in the visible user guidance. Even though the option is not implemented in this file, documenting destructive behavior without a caution can mislead users about a safety-critical operation.

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
The header documentation describes the tool as a line-level PR review utility and says it generates/submits line-level comments, but the implemented comment path uses `gh pr comment` to add a general PR comment only. No code maps comments to files/lines or submits inline review comments, so the documentation overstates the implemented behavior.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The function is documented and presented to the user as approving a PR, but it calls `gh pr review` with `--comment --body "LGTM! 👍"` instead of an approval action. That means it only leaves a comment rather than performing the claimed approval operation.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This command triggers a state-changing GitHub action immediately, without confirmation, dry-run preview, or a clear warning that a review will be posted under the user's authenticated identity. In an agent-skill context, that increases the risk of accidental or socially engineered repository actions, especially if the tool is invoked on the wrong PR or repository.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The rejection/request-changes path posts directly to GitHub without confirmation or an explicit warning, creating a risk of unintended workflow disruption and reputational impact. In a multi-account GitHub helper, accidental execution is more dangerous because the authenticated account may have elevated permissions or act in the wrong organizational context.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The manifest text for the skill and all listed sub-skills is written only in Chinese, with no indication that users can choose another language or that the skill is intentionally limited to a Chinese-speaking audience. Under the policy rule, a fixed language without opt-in or justification is a natural-language policy concern.

Natural-Language Policy Violations

Low
Confidence
92% confidence
Finding
The script's help text, prompts, and status messages are entirely written in Chinese, which enforces a specific language for all users. The file provides no mechanism to select another language or explicitly document that the skill is intended only for a Chinese-speaking audience.

Static analysis

No suspicious patterns detected.