Back to skill

Security audit

Releasenotes

Security checks for vulnerabilities and agentic risk

Overview

This skill is a straightforward local release-notes generator with expected git-read and optional file-output behavior, though users should treat generated Markdown as untrusted before publishing.

Install only if you want a local tool that reads git commit history and generates Markdown release notes. Review or sanitize the generated Markdown before publishing, especially for repositories with untrusted contributors, and provide output paths deliberately when using the -o option.

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
releasenotes.py:34
Finding

Unescaped Git Metadata Allows Markdown and HTML Content Injection

Content
View full analysis

Vulnerability Details

File Location: releasenotes.py, lines 34–38 and 69–73
Vulnerability Type: Markdown content injection through untrusted Git metadata
Risk Level: Medium

Vulnerable Code:

python
for line in out.stdout.strip().split("\n"):
    if not line:
        continue
    parts = line.split("|", 3)
    if len(parts) >= 4:
        commits.append({"hash": parts[0][:8], "msg": parts[1], "author": parts[2], "date": parts[3][:10]})
python
if label in groups:
    lines.append(f"## {label}\n")
    for c in groups[label]:
        lines.append(f"- {c['msg']} (`{c['hash']}` by {c['author']})")
    lines.append("")

Technical Analysis

The application treats commit subjects and author names returned by git log as trusted text. These repository-controlled values are interpolated directly into generated Markdown without escaping Markdown metacharacters or sanitizing raw HTML.

An attacker who can contribute a commit can craft its subject or author identity to contain Markdown links, remote images, raw HTML, misleading headings, or other renderer-specific constructs. The payload is retained when release notes are generated. Its ultimate behavior depends on the Markdown renderer and its security configuration.

The subprocess invocation itself uses a list of arguments without shell=True, so this issue does not provide a shell-command injection path.

Attack Path

  1. An attacker creates or contributes a commit with a crafted subject or author name, such as a deceptive Markdown link, remote tracking image, or raw HTML payload.
  2. A maintainer accepts the commit into a repository.
  3. The maintainer runs releasenotes.py against that repository.
  4. The script reads the attacker-controlled metadata and inserts it verbatim into the generated Markdown.
  5. The generated release notes are published or viewed through a Markdown renderer.
  6. The injected content alters the ...[truncated 796 chars]
Remediation
View remediation

Remediation Suggestions

Treat commit subjects and author names as untrusted content.

  1. Escape Markdown control characters in both fields before interpolation, including backslashes, backticks, brackets, parentheses, asterisks, underscores, heading markers, and angle brackets.
  2. Encode or remove raw HTML. If HTML support is required, process generated content with a maintained sanitizer configured with a strict allowlist.
  3. Consider generating plain-text entries and passing them through a renderer-specific escaping function rather than implementing incomplete ad hoc replacements.
  4. Configure publication platforms to disable raw HTML and active content in Markdown.
  5. Add tests containing malicious author names and commit subjects, including links, images, headings, HTML tags, and multiline or delimiter-like content, and verify that they render only as literal text.
  6. Document that generated release notes contain repository-controlled metadata and must be sanitized before publication in environments that support unsafe Markdown extensions.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/releasenotes.py:34
Finding

Unescaped Git Metadata Allows Markdown and HTML Content Injection in Script Copy

Content
View full analysis

Vulnerability Details

File Location: scripts/releasenotes.py, lines 34–38 and 69–73
Vulnerability Type: Markdown content injection through untrusted Git metadata
Risk Level: Medium

Vulnerable Code:

python
for line in out.stdout.strip().split("\n"):
    if not line:
        continue
    parts = line.split("|", 3)
    if len(parts) >= 4:
        commits.append({"hash": parts[0][:8], "msg": parts[1], "author": parts[2], "date": parts[3][:10]})
python
if label in groups:
    lines.append(f"## {label}\n")
    for c in groups[label]:
        lines.append(f"- {c['msg']} (`{c['hash']}` by {c['author']})")
    lines.append("")

Technical Analysis

This duplicate implementation has the same trust-boundary violation as the root-level script. Commit subjects and author names are controlled by repository contributors but are inserted directly into Markdown output without contextual escaping or HTML sanitization.

Consequently, crafted Git metadata can inject Markdown or raw HTML into release notes. Whether active content can execute depends on the downstream Markdown renderer, but deceptive content and externally loaded resources may remain possible even where script execution is disabled.

The use of subprocess.run with an argument array and no shell prevents the metadata from becoming a shell-command injection vector in this code path.

Attack Path

  1. An attacker introduces a commit whose subject or author name contains a Markdown or HTML payload.
  2. The commit enters the repository history inspected by the tool.
  3. A maintainer executes scripts/releasenotes.py.
  4. The script copies the malicious metadata into a Markdown list item without escaping it.
  5. The output is saved, published, or rendered.
  6. Readers encounter attacker-controlled document content, deceptive navigation, remote resources, or renderer-dependent unsafe HTML behavior.

Impact Assessment

...[truncated 501 chars]

Remediation
View remediation

Remediation Suggestions

  1. Escape all repository-controlled text according to the output context before adding it to Markdown.
  2. Sanitize or encode raw HTML in commit subjects and author names.
  3. Prefer a well-tested Markdown escaping routine and a strict HTML allowlist sanitizer where HTML output is unavoidable.
  4. Disable raw HTML and unsafe extensions in downstream renderers.
  5. Add regression tests proving that crafted links, images, headings, HTML tags, and other formatting characters are emitted as literal text.
  6. Remove the duplicated implementation or centralize the release-note logic in one maintained module so that security fixes cannot be applied to only one copy.
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (4)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill documentation advertises shell execution and file output capabilities, but it does not declare any explicit tool scope such as allowed-tools or permissions. This creates an authorization gap where an agent may invoke shell commands or write files without the skill clearly constraining or signaling those capabilities, increasing the chance of unintended command execution or filesystem modification.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The description contains broad trigger phrases like creating changelogs, summarizing recent commits, and preparing releases, which can match many common user requests. Overly broad activation can cause this skill to be selected in situations where shell access or file-writing behavior is unnecessary, expanding exposure to risky capabilities beyond the intended use case.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · releasenotes.py (reported line 29)May include surrounding context.

python
cmd.append(f"--since={since}")
    if until:
        cmd.append(f"--until={until}")
    out = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
    if out.returncode != 0:
        print(f"Error: {out.stderr.strip()}", file=sys.stderr)
        sys.exit(1)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/releasenotes.py (reported line 29)May include surrounding context.

python
cmd.append(f"--since={since}")
    if until:
        cmd.append(f"--until={until}")
    out = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
    if out.returncode != 0:
        print(f"Error: {out.stderr.strip()}", file=sys.stderr)
        sys.exit(1)

Static analysis

No suspicious patterns detected.