Back to skill

Security audit

研发经理助手

Security checks for vulnerabilities and agentic risk

Overview

This local project-management skill mostly matches its stated purpose, but it can unexpectedly change a Git repository’s active branch and overwrite report files, so it should be reviewed before installation.

Install only if you are comfortable with a Chinese-language local helper that reads configured repositories and writes reports. Before using it on important work, change the Git statistics script to avoid `git checkout`, quote and validate branch arguments, and avoid overwriting existing report files without confirmation.

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

Warning
Location
tools/git-stats.sh:52
Finding

Git Statistics Tool Unexpectedly Modifies the Target Repository

Content
View full analysis

Vulnerability Details

File Location: tools/git-stats.sh, lines 52-57
Vulnerability Type: Repository state modification and unsafe argument handling
Risk Level: Medium

bash
# 检查分支是否存在
if ! git show-ref --verify --quiet refs/heads/$BRANCH; then
    echo "错误: 分支不存在: $BRANCH"
    echo "可用分支:"
    git branch -a
    exit 1
fi

# 切换到指定分支
git checkout $BRANCH > /dev/null 2>&1

Technical Analysis

The tool is documented as a statistics utility, but it executes git checkout and therefore modifies the current branch, index, and potentially the working-tree state of the repository being analyzed. Reading Git history does not require a checkout, so this violates the principle of least modification.

The attacker-controlled or caller-controlled BRANCH variable is also expanded without quotes and without an option terminator. Although this does not directly provide shell command execution, shell word splitting and pathname expansion can alter the arguments passed to Git. A specially constructed option-like ref can also be interpreted as a Git option rather than strictly as a branch name.

The preceding show-ref operation does not make the later checkout option-safe. It verifies a ref assembled under refs/heads/, while the subsequent command passes the original branch string directly to Git's command-line parser.

Attack Path

  1. An attacker or untrusted repository maintainer creates a specially named ref, including an option-like name where the Git implementation permits such a ref to exist.
  2. The user runs git-stats.sh against that repository and supplies the corresponding value as the third argument.
  3. The script verifies the assembled ref but then passes the original value unquoted to git checkout.
  4. Git may interpret the value through option parsing rather than exclusively as a branch name.
  5. Even during ordinary use, the script switches the repository away from the developer's ...[truncated 773 chars]
Remediation
View remediation

Remediation Suggestions

Remove the checkout operation entirely. All statistics commands should query a fully qualified, validated ref without modifying repository state.

  1. Validate the supplied branch name with git check-ref-format --branch.
  2. Reject branch values beginning with -.
  3. Resolve the branch to a full ref or commit identifier before using it.
  4. Quote every variable expansion.
  5. Use -- as an option terminator where the relevant Git command supports it.
  6. Run commands with git -C "$REPO_PATH" instead of changing the process working directory.
  7. Add tests covering whitespace, wildcard characters, option-like values, missing branches, dirty working trees, and repositories whose active branch differs from the requested reporting branch.

A safer design is:

bash
if ! git check-ref-format --branch "$BRANCH" > /dev/null 2>&1; then
    printf 'Invalid branch name: %s\n' "$BRANCH" >&2
    exit 1
fi

case "$BRANCH" in
    -*) printf 'Option-like branch names are not accepted\n' >&2; exit 1 ;;
esac

REF="refs/heads/$BRANCH"
if ! git -C "$REPO_PATH" show-ref --verify --quiet "$REF"; then
    printf 'Branch does not exist: %s\n' "$BRANCH" >&2
    exit 1
fi

git -C "$REPO_PATH" rev-list --count --since="$SINCE_DATE 00:00:00" "$REF"

Apply the same quoted $REF value to all subsequent git log, git diff, and git rev-list operations.

other

Warning
Location
tools/git-stats.sh:77
Finding

Untrusted Git Metadata Is Passed into AI-Consumed Reports Without Delimiting or Sanitization

Content
View full analysis

Vulnerability Details

File Location: tools/git-stats.sh, lines 77-96
Vulnerability Type: Indirect prompt injection through repository-controlled metadata
Risk Level: Medium

bash
git log --since="$SINCE_DATE 00:00:00" --format='%an' $BRANCH | \
    sort | uniq -c | sort -rn | \
    while read count author; do
        last_commit=$(git log --author="$author" --since="$SINCE_DATE 00:00:00" --format='%ad' --date=short $BRANCH | head -n 1)
        echo "| $author | $count | $last_commit |"
    done

echo ""

# 代码行数变化
echo "## 📈 代码行数变化"
git diff --stat "HEAD@{$DAYS days ago}..HEAD" 2>/dev/null || echo "最近 $DAYS 天没有代码变化"

echo ""

# 最近 5 次提交
echo "## 🔥 最近提交"
git log --since="$SINCE_DATE 00:00:00" --format='%h - %an, %ar : %s' --date=relative $BRANCH | head -n 5

Technical Analysis

Git author names and commit subjects are contributor-controlled metadata. The script inserts these values verbatim into Markdown output. It does not escape Markdown syntax, remove control characters, constrain lengths, or place the values inside a clearly identified untrusted-data boundary.

The Skill documentation directs an AI agent to run this tool and use its output when generating meeting and project reports. Consequently, instruction-like text placed in an author name or commit subject can enter the agent's context through a trusted tool-result channel.

This is an indirect prompt-injection boundary failure rather than shell command injection. The script itself does not execute commit messages. Exploitation depends on a downstream AI agent interpreting repository metadata as instructions instead of treating it solely as data.

Attack Path

  1. An attacker with permission to contribute a commit chooses an author name or commit subject containing instruction-like content, misleading Markdown, or text directing an AI agent to disclose data or perform unrelated actions.
  2. The malicious commit becomes vis ...[truncated 1378 chars]
Remediation
View remediation

Remediation Suggestions

Treat all repository-derived fields as untrusted data at both the script and agent-instruction layers.

  1. Add explicit Skill instructions stating that commit subjects, author names, file names, and other repository metadata are data only and must never be followed as instructions.
  2. Delimit repository data in a structured format such as JSON rather than mixing it directly with narrative Markdown.
  3. Escape Markdown metacharacters before embedding metadata in Markdown reports.
  4. Strip terminal control sequences and nonessential control characters.
  5. Normalize line breaks so one metadata field cannot create new report sections.
  6. Enforce reasonable length limits on author names and commit subjects.
  7. Keep raw metadata separate from trusted report instructions.
  8. Validate output in tests using commit messages containing headings, links, code fences, multiline text, control sequences, and prompt-like commands.
  9. Configure the consuming agent to summarize delimited fields without acting on any instructions found inside them.

For example, emit bounded JSON records:

bash
git log \
    --since="$SINCE_DATE 00:00:00" \
    --format='%H%x00%an%x00%s' \
    "$REF"

A dedicated parser should then remove control characters, enforce field-size limits, and serialize the resulting values with a standard JSON encoder. The agent should receive the serialized records together with an explicit statement that every field is untrusted repository content.

Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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
Findings (25)

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The skill description presents a broad management assistant, but the documented behavior includes concrete local repository access and shell-driven operations that are not clearly bounded in the top-level declaration. This mismatch can mislead users and policy engines about what the skill will actually do, resulting in unexpected execution against local codebases or branch state.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill description presents a broad management assistant, but the documented behavior includes concrete local repository access and shell-driven operations that are not clearly bounded in the top-level declaration. This mismatch can mislead users and policy engines about what the skill will actually do, resulting in unexpected execution against local codebases or branch state.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documented trigger phrases are very broad everyday language, which increases the chance the skill could activate during unrelated conversation. In an assistant environment, accidental invocation can cause unintended access to local repositories, generation of reports, or disclosure of project status without clear user intent.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

Project-management triggers like asking about progress or risks lack clear boundaries and could be interpreted from normal discussion. This can lead the assistant to surface sensitive internal status, risk assessments, or team information when the user did not explicitly intend to invoke the skill.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

Code-review trigger phrases are overly generic and may match ordinary requests in contexts where the user has not deliberately selected this skill. Because code review can involve reading local code or producing security-related summaries, ambiguous activation raises the risk of unintended file access and leakage of proprietary source context.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

L296-L297 明确宣称“所有数据存储在本地,不会上传到任何第三方服务”。但 L279-L283 建议该技能进行“每日学习:研究开源项目的最佳实践”和“定期升级”,这与前述纯本地、无外部交互的表述存在意图层面的冲突,因为研究开源项目通常意味着访问外部资源。

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill advertises and instructs execution of local shell scripts, reads repositories, and writes reports, but it does not declare any explicit tool scope such as allowed-tools or permissions. That makes the skill's effective capabilities broader and less auditable, increasing the chance that an agent executes file or shell actions without clear user consent or policy enforcement.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The trigger examples use very broad natural-language prompts such as generating reports or reviewing PRs, which can cause the agent to invoke shell/file-capable tooling in response to ordinary conversation. In a skill that can access local repositories and write files, ambiguous triggers raise the risk of unintended actions without sufficiently explicit user intent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The skill name, description, and author metadata are entirely in Chinese, and the file provides no indication that users can choose another language or that the skill is intentionally limited to a Chinese-speaking context. This can violate language/locale policy when a skill implicitly enforces a specific language without opt-in or documented justification.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script performs git checkout $BRANCH even though its stated purpose is only to collect repository statistics. Changing branches mutates the user's working repository state, can disrupt in-progress work, and may trigger checkout side effects or failures if there are local changes.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

For a management-reporting utility, adding the ability to modify repository state exceeds the minimum required capability and violates least surprise. In practice this can alter the operator's workspace, interfere with automation jobs, and create avoidable operational risk unrelated to the reporting goal.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script changes the current branch without warning, confirmation, or rollback. This can surprise users, break local workflows, conflict with uncommitted changes, and in CI or shared environments produce unintended side effects beyond simple reporting.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code file contains natural-language descriptions and CLI help text in Chinese only, which effectively forces a specific language on users. The policy allows locale constraints only when users are given a choice or when the restriction is explicitly justified, neither of which is present here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The argparse description and help strings are all written in Chinese, so users are required to interact with the tool in that language. This is a natural-language policy issue because no alternative locale or user-selectable language behavior is offered.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script writes directly to the user-supplied output path using shell redirection and will silently truncate an existing file before writing the generated report. This can cause unintended data loss or overwriting of important files if the caller mistypes a path or is tricked into supplying a sensitive target path, but it does not by itself enable code execution or privilege escalation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

整个技能说明和示例均以中文呈现,并以“研发经理助手”面向用户交互,但没有说明是否支持其他语言或允许用户自行选择输出语言。若该技能面向更广泛用户群,这种默认单一语言约束可能不符合语言/区域选择政策。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This manifest file contains natural-language content exclusively in Chinese, including comments and user-facing example values. Under the stated policy, forcing a specific language without user opt-in can be a locale-policy violation when no justification or alternative language is provided.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown file is entirely written in Chinese and provides no indication that language selection is optional or limited to a justified Chinese-only context. Under the policy rule for language or locale constraints, this can be a natural-language policy violation because it implicitly fixes the skill's operating language without user choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script's user-facing comments and terminal messages are entirely in Chinese, including the operational guidance shown to the user. For an all-file-types policy check, this is a locale/language constraint presented without opt-in or an explicit statement that the skill is region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

This markdown template is entirely written in Chinese, including headings, labels, and the final attribution, with no indication that the user can choose another language. Under the policy for natural-language violations, a skill that effectively forces a specific language without opt-in should be flagged unless the locale restriction is documented and justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

Comments and help/output strings such as the usage text are written only in Chinese, which imposes a specific language on all users. The policy allows locale constraints only when there is explicit opt-in or clear documented justification, neither of which is present here.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

L040 的 docstring 明确写着“支持 YAML 或 JSON”,但实际实现中 L47-L49 只使用 json.load 解析文件,没有任何 YAML 处理逻辑。这属于文档对能力的主动性错误描述,和实际行为直接不一致。

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The success output is emitted only in Chinese, continuing the single-language constraint during normal operation. Since the file does not offer users a language choice or explain a locale-specific purpose, this conflicts with the stated language policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The error message shown to users is only in Chinese, which enforces one language for troubleshooting as well. Without a documented and justified locale restriction, this is a policy violation under the language/locale rule.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The script's natural-language interface, including comments, usage output, errors, and status messages, is written exclusively in Chinese. For a general-purpose tool, forcing a single language without opt-in can violate language or locale policy when no regional constraint is documented.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.