Back to skill

Security audit

App Store Changelog

Security checks for vulnerabilities and agentic risk

Overview

This skill is a small, purpose-aligned release-note helper, with one real but limited command-hardening issue around unvalidated git refs.

Install only if you are comfortable letting the skill read commit history and touched file names from repositories where you use it. When passing refs manually, use trusted tag or commit names; avoid copying untrusted ref arguments into the command until the script validates revisions and quotes the git range.

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
scripts/collect_release_changes.sh:4
Finding

Unvalidated Git Revision Allows Command-Line Option Injection

Content
View full analysis

Vulnerability Details

File Location: scripts/collect_release_changes.sh, lines 4-5, 13-17, 27, and 30
Vulnerability Type: Git command-line option injection through an unquoted and unvalidated revision range
Risk Level: Medium

Vulnerable Code

bash
since_ref="${1:-}"
until_ref="${2:-HEAD}"

if [[ -z "${since_ref}" ]]; then
  if git describe --tags --abbrev=0 >/dev/null 2>&1; then
    since_ref="$(git describe --tags --abbrev=0)"
  fi
fi

range=""
if [[ -n "${since_ref}" ]]; then
  range="${since_ref}..${until_ref}"
else
  range="${until_ref}"
fi

git log --reverse --date=short --pretty=format:'%h|%ad|%s' ${range}

git log --reverse --name-only --pretty=format:'--- %h %s' ${range} | sed '/^$/d'

Technical Analysis

The script accepts Git revisions from positional arguments and incorporates them into range without validating that they resolve to commits. It then expands ${range} without quotation and does not use an appropriate option/revision disambiguation mechanism.

If since_ref remains empty, until_ref becomes the entire argument supplied to both git log commands. A value beginning with -- may consequently be interpreted as a Git command-line option rather than as a revision. For example, Git's --output=<path> option can redirect command output to a local file selected by the caller.

The unquoted expansion additionally subjects the value to shell word splitting and pathname expansion. Shell metacharacters embedded in the variable are not reparsed as shell operators, so this issue does not by itself provide arbitrary shell-command execution. The confirmed primitive is injection of supported git log options.

Attack Path

  1. An attacker influences a requested revision used to generate release notes.
  2. The caller invokes the script with an empty first argument and an attacker-controlled second argument.
  3. The script assigns the second ...[truncated 1298 chars]
Remediation
View remediation

Remediation Suggestions

Validate every user-provided revision with git rev-parse --verify and convert it to a commit object ID before constructing a range. Reject values that do not resolve to commits. Keep all variable expansions quoted so the shell cannot perform word splitting or pathname expansion.

A hardened implementation can use the following pattern:

bash
if [[ -n "${since_ref}" ]]; then
  since_oid="$(git rev-parse --verify "${since_ref}^{commit}")" || {
    printf 'Invalid starting revision: %s\n' "${since_ref}" >&2
    exit 1
  }
fi

until_oid="$(git rev-parse --verify "${until_ref}^{commit}")" || {
  printf 'Invalid ending revision: %s\n' "${until_ref}" >&2
  exit 1
}

if [[ -n "${since_ref}" ]]; then
  range="${since_oid}..${until_oid}"
else
  range="${until_oid}"
fi

git log --reverse --date=short \
  --pretty=format:'%h|%ad|%s' "${range}"

git log --reverse --name-only \
  --pretty=format:'--- %h %s' "${range}" | sed '/^$/d'

Additional hardening measures include:

  • Rejecting arguments that begin with - before invoking Git.
  • Using resolved hexadecimal object IDs rather than raw caller input.
  • Applying the same validation and quoting to both git log calls.
  • Testing malformed refs, whitespace-containing values, wildcard characters, and option-like values.
  • Running the skill with least-privilege filesystem permissions to limit the impact of unintended file writes.
Vulnerability Patterns
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (1)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The script is related to release-change collection from git history, so it is adjacent to the declared purpose, but it stops at extracting raw commit logs and touched files. The description claims it creates user-facing App Store release notes and summarizes user-impacting changes, which this code does not do. It also prints the repository root path, an undeclared behavior. Therefore the implementation materially underdelivers and differs from the stated primary behavior.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.