Back to skill

Security audit

commit-history-exporter

Security checks for vulnerabilities and agentic risk

Overview

The skill is a repository history exporter, but its shipped shell scripts use unsafe command construction and encourage insecure SVN password handling, so it needs review before installation.

Install only after reviewing and preferably fixing the scripts. Avoid passing SVN passwords on the command line; use SVN's credential cache or an interactive/protected secret flow. Treat exported reports as sensitive because they may include names, emails, commit messages, file paths, and repository URLs.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/export_git_commits.sh:32
Finding
Arbitrary Command Execution Through Git Log Argument Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/export_git_commits.sh`, lines 32–45, 68, 92, 119, and 154 **Vulnerability Type**: Shell command injection through `eval` **Risk Level**: High ### Vulnerable Code ```bash # Build git log command arguments GIT_LOG_ARGS="--pretty=format:'%H|%an|%ae|%ad|%s' --date=iso" if [ -n "$AUTHOR" ]; then GIT_LOG_ARGS="$GIT_LOG_ARGS --author=\"$AUTHOR\"" fi if [ -n "$START_DATE" ]; then GIT_LOG_ARGS="$GIT_LOG_ARGS --since=\"$START_DATE\"" fi if [ -n "$END_DATE" ]; then GIT_LOG_ARGS="$GIT_LOG_ARGS --until=\"$END_DATE\"" fi ``` The constructed command string is subsequently executed through `eval` in multiple locations: ```bash eval git log $GIT_LOG_ARGS ``` It is also used when calculating statistics: ```bash total_commits=$(eval git log $GIT_LOG_ARGS --oneline | wc -l) ``` ### Technical Analysis `AUTHOR`, `START_DATE`, and `END_DATE` are caller-controlled positional arguments. The script embeds them into a shell command string and then passes that string to `eval`. Quoting the values while constructing the string does not make this safe. `eval` causes the shell to parse the resulting text a second time. Embedded quotation marks, command substitutions, shell separators, or redirection operators can therefore terminate the intended Git argument and introduce additional commands. Every supported output branch invokes the affected command, so the vulnerability is reachable when exporting Markdown, CSV, or JSON. The final statistics command also invokes the same injection sink. ### Attack Path 1. An attacker supplies a crafted author or date argument, for example an author containing: ```text "; touch /tmp/git_skill_pwned; # ``` 2. The script concatenates the value into `GIT_LOG_ARGS`. 3. An affected branch executes: ```bash eval git log $GIT_LOG_ARGS ``` 4. `eval` reparses the injected quotation mark and semicolon as shell syntax. 5. The injected command executes independent ...[truncated 761 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Remove every use of `eval` and construct arguments with a Bash array: ```bash git_log_args=( "--pretty=format:%H|%an|%ae|%ad|%s" "--date=iso" ) if [[ -n "$AUTHOR" ]]; then git_log_args+=(--author="$AUTHOR") fi if [[ -n "$START_DATE" ]]; then git_log_args+=(--since="$START_DATE") fi if [[ -n "$END_DATE" ]]; then git_log_args+=(--until="$END_DATE") fi git log "${git_log_args[@]}" total_commits=$(git log "${git_log_args[@]}" --oneline | wc -l) ``` Apply the same array-based invocation to the Markdown, CSV, JSON, and statistics branches. Each user value must remain one argument and must never be reparsed as shell source. Consider validating date inputs as an additional defense-in-depth measure. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/export_svn_commits.sh:39
Finding
SVN Command Injection and Plaintext Credential Exposure<![CDATA[ ## Vulnerability Details **File Location**: `scripts/export_svn_commits.sh`, lines 15–16, 39–44, and 71 **Vulnerability Type**: Shell command injection and insecure handling of authentication secrets **Risk Level**: High ### Vulnerable Code ```bash SVN_USER="${6:-}" SVN_PASS="${7:-}" ``` ```bash # Build authentication arguments AUTH_ARGS="" if [ -n "$SVN_USER" ]; then AUTH_ARGS="--username \"$SVN_USER\"" fi if [ -n "$SVN_PASS" ]; then AUTH_ARGS="$AUTH_ARGS --password \"$SVN_PASS\"" fi ``` ```bash eval svn log $AUTH_ARGS -r ${START_REV:-1}:${END_REV} -v ``` ### Technical Analysis The script accepts an SVN username and password as positional command-line arguments. It incorporates both values into an `AUTH_ARGS` command string that is executed with `eval`. The start and end revision values are also inserted into the evaluated command without safe argument separation. Consequently, any of the following inputs may introduce shell syntax: - `SVN_USER` - `SVN_PASS` - `START_REV` - `END_REV` Because `eval` performs another shell parsing pass, embedded separators, substitutions, quotation marks, and redirections can execute commands outside the intended `svn log` operation. Separately, supplying the password as a positional argument exposes the secret beyond the SVN client. Depending on the operating environment, the password may be retained in shell history, process accounting, orchestration logs, AI tool-call logs, or other command telemetry. During execution, command-line arguments may also be observable by other local processes or users where process inspection permissions allow it. ### Attack Path #### Command-injection path 1. An attacker controls or influences one of the SVN exporter arguments. 2. The attacker supplies a revision such as: ```text 1; touch /tmp/svn_skill_pwned; # ``` 3. The value is inserted into the evaluated revision expression: ```bash eval svn log $AUTH_ARGS -r ${START_REV:-1}:${END_REV} -v ``` ...[truncated 1602 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove `eval` and use a Bash argument array: ```bash svn_args=(log) if [[ -n "$SVN_USER" ]]; then svn_args+=(--username "$SVN_USER") fi svn_args+=(-r "${start_rev}:${end_rev}" -v) svn "${svn_args[@]}" ``` 2. Strictly validate revisions before invocation: ```bash [[ "$START_REV" =~ ^[0-9]+$ ]] || exit 1 [[ "$END_REV" == "HEAD" || "$END_REV" =~ ^[0-9]+$ ]] || exit 1 ``` 3. Do not accept passwords as positional command-line arguments. Prefer: - SVN's protected credential cache. - Interactive credential prompting. - A file descriptor or protected secret mechanism provided by the execution environment. 4. If non-interactive password handling is unavoidable, ensure the secret is obtained from a protected source, is never logged, and is not included in shell command text. 5. Update `SKILL.md` examples so they no longer encourage placing plaintext passwords directly in command lines. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/export_git_commits.sh:15
Finding
Unsanitized Author Values Used in Git Report Paths<![CDATA[ ## Vulnerability Details **File Location**: `scripts/export_git_commits.sh`, line 15 **Vulnerability Type**: Path traversal and unintended file creation **Risk Level**: Medium ### Vulnerable Code ```bash # Output filename OUTPUT_FILE="git_commits_${AUTHOR}_$(date +%Y%m%d_%H%M%S).${FORMAT}" ``` The value is later used directly in report redirections, for example: ```bash echo "# Git 提交记录报告" > "$OUTPUT_FILE" echo "" >> "$OUTPUT_FILE" ``` ### Technical Analysis `AUTHOR` is a caller-controlled string and is inserted directly into a filesystem path. Quoting `"$OUTPUT_FILE"` prevents shell word splitting but does not neutralize path separators or `..` traversal components. An author value containing `/` and `..` can cause path normalization to resolve outside the intended repository directory when the required intermediate directories exist. The script does not constrain output to a dedicated export directory and does not canonicalize or validate the final path before opening it. The timestamp suffix makes targeting an exact existing filename less straightforward, but it does not prevent creation of reports in unintended writable directories. Predictable timestamps and filesystem links may also increase overwrite or redirection risk in environments where an attacker can prepare the destination. ### Attack Path 1. The attacker ensures a suitable intermediate directory exists in the repository, such as `git_commits_x`. 2. The attacker supplies an author value containing traversal components: ```text x/../../outside ``` 3. The resulting relative path resembles: ```text git_commits_x/../../outside_<timestamp>.markdown ``` 4. Filesystem path resolution escapes the repository directory. 5. The report is created in an unintended parent or sibling directory if that destination is writable. ### Impact Assessment The vulnerability can create report files outside the selected Git repository under the privileges of the invoking account. The ...[truncated 462 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Do not derive output paths directly from author input. Generate reports inside a fixed directory and sanitize any human-readable filename component: ```bash export_dir="$PROJECT_PATH/.commit-exports" mkdir -p -- "$export_dir" chmod 700 "$export_dir" safe_author=$(printf '%s' "${AUTHOR:-all}" | tr -c 'A-Za-z0-9._-' '_') [[ "$safe_author" != "." && "$safe_author" != ".." ]] || safe_author="all" OUTPUT_FILE="$export_dir/git_commits_${safe_author}_$(date +%Y%m%d_%H%M%S).${FORMAT}" ``` Additionally: - Reject author filename components containing `/`, backslashes, control characters, or `..`. - Canonicalize the export directory and verify that the final parent directory remains beneath it. - Use restrictive report permissions, such as `umask 077`. - Consider using `mktemp` within the fixed export directory to avoid predictable-name and symlink races. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/export_svn_commits.sh:18
Finding
Unsanitized Author Values Used in SVN Report Paths<![CDATA[ ## Vulnerability Details **File Location**: `scripts/export_svn_commits.sh`, line 18 **Vulnerability Type**: Path traversal and unintended file creation **Risk Level**: Medium ### Vulnerable Code ```bash # Output filename OUTPUT_FILE="svn_commits_${AUTHOR:-all}_$(date +%Y%m%d_%H%M%S).${FORMAT}" ``` The generated path is subsequently opened through report redirections, including: ```bash echo "# SVN 详细提交记录报告" > "$OUTPUT_FILE" ``` and: ```bash python3 << 'PYTHON_SCRIPT' >> "$OUTPUT_FILE" ``` ### Technical Analysis The caller-controlled `AUTHOR` value is embedded directly in the report path without filename sanitization. Shell quoting protects against argument splitting and glob expansion, but it does not prevent `/` or `..` from affecting filesystem resolution. If matching intermediate directories exist, traversal components can direct the generated report outside the selected SVN working copy. The report destination is not checked against a trusted export root before it is opened. As with the Git exporter, the timestamp reduces direct control over the complete filename but does not prevent unintended placement. Symbolic links or prepared directories can increase the practical risk. ### Attack Path 1. An attacker prepares or identifies an intermediate directory such as `svn_commits_x`. 2. The attacker invokes the script with an author value such as: ```text x/../../outside ``` 3. The script generates a path resembling: ```text svn_commits_x/../../outside_<timestamp>.detailed ``` 4. Filesystem path resolution escapes the SVN working-copy directory. 5. The script writes the detailed report to an unintended writable location. ### Impact Assessment An attacker can redirect report creation outside the selected SVN repository, subject to filesystem permissions and the existence of usable intermediate paths. The resulting file may disclose repository metadata, including author identities, revision numbers, dates, commit messages ...[truncated 285 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Write reports only into a fixed, permission-restricted export directory and sanitize the author component: ```bash export_dir="$PROJECT_PATH/.commit-exports" mkdir -p -- "$export_dir" chmod 700 "$export_dir" safe_author=$(printf '%s' "${AUTHOR:-all}" | tr -c 'A-Za-z0-9._-' '_') [[ "$safe_author" != "." && "$safe_author" != ".." ]] || safe_author="all" OUTPUT_FILE="$export_dir/svn_commits_${safe_author}_$(date +%Y%m%d_%H%M%S).${FORMAT}" ``` Also: - Reject path separators, traversal sequences, and control characters in filename components. - Verify the canonical destination remains under the fixed export directory. - Set `umask 077` before creating reports. - Prefer `mktemp` in the trusted export directory to reduce predictable-path and symbolic-link risks. ]]>
Vulnerability Patterns
  • 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
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
该代码的总体方向与声明部分一致,确实是在导出代码提交记录,并支持作者、时间范围、项目路径过滤,也能输出多种格式。但存在明显的功能性描述不符:首先,代码会检查 .git 目录并调用 git log/git show,完全没有任何 SVN 支持;其次,声明中的 Detailed 格式未实现,支持格式仅为 markdown、csv、json;再次,所谓‘完整提交日志’并未实现,脚本没有导出完整 diff 或更完整的提交内容,只输出 commit id、作者、时间、message 和文件变更信息。因此应判定为描述与实际行为存在实质性不匹配。

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
描述与代码存在实质性不一致。首先,声明覆盖 SVN 和 Git,但代码块只处理 SVN 仓库,未见任何 Git 相关逻辑。其次,声明称支持多种导出格式,但代码中仅 detailed 分支有明确实现,markdown/csv/json 分支只是“原有代码”占位,无法证明已实现。再次,声明提到按时间范围过滤,而当前脚本参数与核心查询主要依据起止修订号范围,不是等价的时间过滤。最后,脚本在无认证时会读取本地 .svn/wc.db SQLite 数据库作为回退,这属于实际资源访问行为,虽然可视为实现细节,但描述未体现这种本地数据库读取方式。总体上,代码的实际范围明显小于且不同于声明,因此应判定为不匹配。

Missing User Warnings

High
Confidence
98% confidence
Finding
The documentation instructs users to pass SVN usernames and passwords directly on the command line, which can expose secrets through shell history, process listings, audit logs, and terminal recordings. In a skill specifically handling repository access, this is more dangerous because the same credentials may grant broad access to source code history and internal project information.

Missing User Warnings

High
Confidence
98% confidence
Finding
This section again recommends supplying SVN passwords inline in the command, without a clear security warning. That practice materially increases credential leakage risk to local users, monitoring tools, CI logs, and support screenshots, and the resulting compromise could expose private repository contents and historical commit data.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The trigger phrase uses an open-ended '等类似请求', which can cause the skill to activate on broader requests than intended. In this context, that raises the chance of unplanned repository-history access or export of commit metadata when a user asked something only loosely related, increasing the risk of unintended disclosure of developer activity, file paths, and commit messages.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The script and surrounding guide present output as SVN commit-record/history reporting, but the data source is only the local .svn/wc.db working-copy metadata. In this skill’s context, that can mislead users into believing they exported authoritative commit history or detailed logs when commit messages, deleted history, and non-fetched revisions are unavailable, creating integrity and audit errors.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The script's comments, status messages, errors, and usage text are all written in Chinese, which imposes a specific language on users without any opt-in or documented regional justification. This matches the policy category for language or locale constraints expressed in natural-language content.

Description-Behavior Mismatch

Medium
Confidence
93% confidence
Finding
The manifest states the skill supports Markdown, CSV, JSON, and Detailed formats, with Detailed including full commit logs. In code, FORMAT is documented and enforced as only markdown, csv, or json, and any other value is rejected, so the implemented behavior does not match the advertised capability.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The script exports author email addresses from repository history into generated reports without minimization, masking, or any warning that personally identifiable information will be written to disk. In this skill context, the tool is explicitly designed to export and share commit history, which increases the chance that reports are redistributed beyond the original repository audience and exposes contributor contact data unnecessarily.

Context-Inappropriate Capability

Medium
Confidence
96% confidence
Finding
The script accepts SVN credentials as positional command-line arguments and later uses them to build an SVN command. Command-line arguments are commonly exposed via process listings, shell history, audit logs, and orchestration telemetry, so this creates a real credential-exposure risk even if the feature is intended to access protected logs. In this skill context, exporting commit history does not inherently require insecure password handling, so the behavior is more dangerous than necessary.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script not only accepts credentials on the command line but does so without any warning about password exposure risks. This increases the chance users will paste sensitive credentials into an unsafe invocation pattern, leading to accidental disclosure through ps output, shell history, CI logs, or agent traces. The skill's repository-export purpose makes this unnecessary and elevates concern because users may trust automation to handle secrets safely.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The comment at L151 says it queries modifications for the specified author, and the code tries to read sys.argv[1] at L152. However, because the here-document invocation is malformed for passing arguments, the Python script does not actually receive "$AUTHOR", so the documented filtering intent contradicts the implemented behavior.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
L004 的描述和触发短语全部以中文给出,文件整体也仅提供中文使用方式,未说明这是面向特定中文环境的区域性技能,也未给出语言可选项。若组织要求不得在无用户选择的情况下强制特定语言,这属于自然语言层面的 locale/policy 风险。

Natural-Language Policy Violations

Low
Confidence
77% confidence
Finding
A language-specific skill reference can be a policy concern when it implicitly forces one language without stating that the content is intended for that locale or offering alternatives. This file presents all user-facing guidance exclusively in Chinese with no opt-in or documented locale scope.

Missing User Warnings

Low
Confidence
89% confidence
Finding
This markdown file documents commands that export git history to TXT, CSV, and JSON files, including author and email fields. Because commit logs can contain personal data and the outputs persist on disk, a brief warning about handling and sharing exported files would help users understand the privacy impact.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
This markdown file presents all instructions and examples exclusively in Chinese, with no indication that the skill is region-specific or that users may choose another language. Under the policy rule for natural-language violations, forcing a specific language without user opt-in is a reportable issue.

Missing User Warnings

Low
Confidence
82% confidence
Finding
This markdown file includes examples that print the repository URL from the local SVN database and later sections query and enumerate author names and file histories. Because the document does not warn that these outputs may reveal internal infrastructure details and personal contribution metadata, users are not alerted to the privacy implications of running the examples.

Intent-Code Divergence

Low
Confidence
88% confidence
Finding
The report generator docstring and printed headings say 'SVN 提交记录报告' even though the report is derived solely from local working-copy state. That wording can cause users to overtrust incomplete results, especially in compliance, forensics, or personnel-review workflows where source accuracy matters.

Natural-Language Policy Violations

Low
Confidence
94% confidence
Finding
All user-facing comments and terminal output are written in Chinese, with no indication that the skill is region-specific or that another language can be selected. This is a natural-language policy concern because it imposes a specific language/locale without opt-in.

Static analysis

No suspicious patterns detected.