Back to skill

Security audit

GitHub Release Workflow

Security checks for vulnerabilities and agentic risk

Overview

This release workflow is mostly coherent, but its bundled CLI can run injected shell commands and can publish all unignored repository changes without review.

Install only if you are comfortable reviewing or fixing the CLI first. Do not run gh-release release with untrusted version strings, and review git status plus the staged diff before any commit or push because the tool stages every unignored file in the repository.

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
release.py:9
Finding

Arbitrary Command Execution Through Unsanitized Release Version

Content
View full analysis
None: """Run shell command""" print(f"→ {cmd}") result = subprocess.run(cmd, shell=True, check=check) if result.returncode != 0: sys.exit(result.returncode) def cmd_release(args) -> None: """Create a new release""" version = args.version print(f"Creating release {version}...") # Stage run("git add .") # Commit run(f'git commit -m "release: {version}"') # Tag run(f'git tag -a {version} -m "Version {version}"') # Push run("git push") run(f"git push origin {version}") ``` ### Technical Analysis The `run` function executes command strings through the operating-system shell. The `version` argument is supplied by the CLI user and is interpolated directly into three command strings without validation or shell-safe quoting. An attacker can include shell metacharacters or quote delimiters in the version value. These characters can terminate the intended Git argument and introduce an additional shell command. The vulnerability affects the commit, tag, and tag-push operations. The use of double quotes around some interpolations does not prevent exploitation because an input containing a double quote can terminate the quoted section. The final `git push origin` command interpolates the value without any quoting at all. ### Attack Path 1. An attacker gains the ability to influence the version passed to the release command. This may occur through direct CLI access, a wrapper script, or automated release input. 2. The attacker supplies a crafted value containing shell syntax, for example: ```bash gh-release release 'v1.0.0"; id; #' ``` 3. `cmd_release` inserts that value into a command such as: ```bash ...[truncated 1142 chars]
Remediation
View remediation
None: print("→", " ".join(cmd)) result = subprocess.run(cmd, shell=False, check=check) if result.returncode != 0: sys.exit(result.returncode) ``` 2. Invoke Git without constructing shell command strings: ```python run(["git", "commit", "-m", f"release: {version}"]) run(["git", "tag", "-a", version, "-m", f"Version {version}"]) run(["git", "push"]) run(["git", "push", "origin", version]) ``` 3. Validate the version against an explicit supported format before using it. For example, require a Semantic Versioning tag beginning with `v` and reject whitespace, control characters, shell metacharacters, and option-like values. 4. Insert `--` where supported to prevent a version beginning with `-` from being interpreted as a Git option. 5. Add automated tests covering quote characters, command separators, substitutions, newlines, leading hyphens, and malformed Semantic Versioning values. 6. Run release automation with a minimally privileged account and narrowly scoped repository credentials to reduce the impact of future command-execution defects. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
release.py:34
Finding

Unrestricted Repository Staging Can Commit and Publish Sensitive Files

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (8)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill’s declared purpose presents it as a professional GitHub release workflow, but the actual behavior is primarily a set of generic shell commands that can mutate a repository and publish tags, while key claimed safeguards or capabilities are not implemented. This mismatch can mislead users or downstream agents into trusting and running release-affecting commands under false assumptions about validation, documentation updates, or CI/CD setup, making accidental or premature releases more likely.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
99% confidence
Finding

This is a true tool-parameter abuse issue because the skill wraps a powerful execution primitive and feeds it unsanitized parameters derived from user input. In a release automation context, users are likely to trust the tool and supply version strings without realizing they can be interpreted by the shell, making arbitrary command execution especially dangerous.

Content

Scanner excerpt · release.py (reported line 12)May include surrounding context.

python
def run(cmd: str, check: bool = True) -> None:
    """Run shell command"""
    print(f"→ {cmd}")
    result = subprocess.run(cmd, shell=True, check=check)
    if result.returncode != 0:
        sys.exit(result.returncode)

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 58)May include surrounding context.

md
### 2. Update

- Update version in `pyproject.toml`
- Add entry to `CHANGELOG.md`

### 3. Release

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill includes shell commands that perform impactful repository operations (git add ., git commit, git tag, git push, and optional gh release create) but does not declare any tool scope or permissions boundary. In an agent setting, this can enable unexpected execution of local and remote state-changing commands without explicit authorization, increasing the risk of unintended code publication or tag/release creation.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
98% confidence
Finding

The helper executes arbitrary shell strings with shell=True, and several callers interpolate user-controlled CLI input directly into those strings. In particular, the release version argument is inserted into git commit/tag/push commands, so a crafted version value can trigger command injection and execute arbitrary OS commands on the operator's machine.

Content

Scanner excerpt · release.py (reported line 12)May include surrounding context.

python
def run(cmd: str, check: bool = True) -> None:
    """Run shell command"""
    print(f"→ {cmd}")
    result = subprocess.run(cmd, shell=True, check=check)
    if result.returncode != 0:
        sys.exit(result.returncode)

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The docstring and CLI help describe this command as only initializing a git repository, but the implementation additionally changes repository git config to fixed identity values. That is a materially different side effect from simple initialization and can misattribute future commits.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest describes a professional GitHub release workflow covering releases, version/tag management, conventional commits, documentation updates, and CI/CD setup. In practice, this file only stages all files, creates a release commit, tags it, and pushes via git; it does not interact with GitHub release APIs or implement the other claimed workflow capabilities.

Content

No source excerpt is available for this finding.

Unverifiable Dependency: setuptools has 10 known advisory(ies) (CVE-2013-1633 (Setuptools vulnerable to Man-in-the-middle attacks); CVE-2025-47273 (setuptools has a path traversal vulnerability in PackageIndex.download that lead); CVE-2024-6345 (setuptools vulnerable to Command Injection via package URL) +7 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
40% confidence
Finding

Dependency has known vulnerabilities (CVEs). Using packages with unpatched security flaws exposes the environment to known exploits.

Content

No source excerpt is available for this finding.