Back to skill

Security audit

Issue Prioritizer

Security checks for vulnerabilities and agentic risk

Overview

This skill is mostly a coherent GitHub issue triage helper, but its history cleanup can delete unrelated local directories if pointed at a broad path.

Install only if you are comfortable with local run files being created and pruned. Avoid passing --history-dir as your home directory, a project root, /tmp, or any shared directory; use a dedicated empty state directory for this skill and keep --retain at a conservative value until the cleanup logic is constrained.

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

Error
Location
scripts/fetch-issues.sh:838
Finding
Arbitrary Recursive Deletion Through Unrestricted History Directory Retention<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fetch-issues.sh`, lines 838-858 **Vulnerability Type**: Unsafe filesystem deletion caused by an unrestricted user-controlled retention root **Risk Level**: High ### Vulnerable Code ```bash if [[ -d "$HISTORY_DIR" ]]; then mapfile -t RUN_DIRS < <( find "$HISTORY_DIR" -mindepth 1 -maxdepth 1 -type d -printf '%T@ %p\n' \ | sort -nr \ | while IFS= read -r line; do printf '%s\n' "${line#* }" done ) if [[ "${#RUN_DIRS[@]}" -gt "$RETAIN" ]]; then for ((i = RETAIN; i < ${#RUN_DIRS[@]}; i++)); do if [[ "${RUN_DIRS[$i]}" == "$WORKDIR" ]]; then continue fi rm -rf "${RUN_DIRS[$i]}" done fi fi ``` ### Technical Analysis The `--history-dir` argument accepts an arbitrary filesystem directory. During retention cleanup, the script assumes that every immediate child directory under `HISTORY_DIR` is an issue-prioritizer run and passes older entries directly to `rm -rf`. There is no validation that a deletion candidate: - Uses the expected run-directory naming convention. - Contains a valid issue-prioritizer manifest. - Was created by this script. - Remains inside a dedicated application-owned state directory after canonicalization. - Is not a sensitive directory such as the user's home directory, a project directory, or a shared state directory. Consequently, setting `HISTORY_DIR` to a broad directory causes unrelated child directories to be included in `RUN_DIRS`. A low retention value can then cause those unrelated directories to be recursively deleted. Quoting the path prevents shell word splitting and command injection, but it does not address the authorization flaw: the script is still intentionally issuing `rm -rf` against insufficiently validated paths. This behavior also exceeds the Skill's declared read-only operation. Although it does not mutate the remote GitHub repository, it can destructively modify the local filesystem. ...[truncated 1827 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Use a dedicated retention root** - Default to the application-specific state directory. - Do not permit broad directories such as `/`, `$HOME`, `/home`, `/tmp`, or an existing project root to serve as retention roots. 2. **Canonicalize and validate all paths** - Resolve `HISTORY_DIR`, `WORKDIR`, and each deletion candidate with `realpath` or `readlink -f`. - Verify that every candidate is a strict descendant of the canonical history directory. - Reject empty paths and dangerous canonical roots. 3. **Identify owned run directories** - Delete only directories whose names match a strict run identifier pattern. - Require a valid `manifest.json` containing the expected application identity and run identifier. - Confirm that the manifest's canonical `workdir` matches the candidate directory. 4. **Separate run discovery from arbitrary child discovery** - Replace unrestricted `find ... -type d` enumeration with a constrained pattern, such as application-generated run names. - Prefer maintaining an explicit run index rather than treating all child directories as owned runs. 5. **Add destructive-operation safeguards** - Refuse retention cleanup when a custom history directory is not empty and contains unrecognized entries. - Consider requiring explicit confirmation before applying retention to a non-default location. - Log each validated deletion target before deletion. 6. **Avoid broad recursive deletion where possible** - Delete only known files and directories within validated run roots. - If `rm -rf` remains necessary, use a helper that enforces ownership markers and containment checks immediately before deletion. 7. **Add regression tests** - Verify that `--history-dir "$HOME"` and other broad paths are rejected. - Verify that unrelated sibling directories are never deleted. - Test canonical-path containment, whitespace in paths, custom work directories, and retention v ...[truncated 25 chars]
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • 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 (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description says the skill prioritizes GitHub issues and provides ranked triage recommendations in a read-only manner. The supplied code chunk does not implement prioritization or contributor recommendations; instead, it is a test harness for another script (`fetch-issues.sh`). Its primary behavior is validating data collection and pipeline mechanics: mocking `gh`, checking structured error output, excluding issues with linked open PRs, handling `--resume` and `--diff-from`, pruning retained run directories, and resetting `errors.log`. While these behaviors may support a larger issue-triage system and remain read-only with respect to GitHub, the actual code’s purpose is materially different from the declared user-facing capability. Therefore this is a description/behavior mismatch.

Tool Parameter Abuse

High
Category
Tool Misuse
Content
# ── Step 4: Split into batches (by size, not by count) ───────────────────────

rm -f "$WORKDIR"/batches/batch-*.json "$WORKDIR"/batch-*.json 2>/dev/null || true

if [[ "$REMAINING" -eq 0 ]]; then
  NUM_BATCHES=0
Confidence
95% confidence
Finding
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill instructs the agent to execute shell commands (`bash`, `cat`) and use the `gh` CLI, but it declares no `permissions` or `allowed-tools` scope. That creates an implicit capability boundary bypass: a caller may invoke a skill that appears harmless/read-only while it can access the shell and local files, increasing the chance of unintended command execution or data exposure if any inputs are attacker-controlled.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
Automatic pruning of workdirs is an unnecessary destructive capability for a fetch/triage helper and expands the blast radius beyond data collection. If HISTORY_DIR is pointed at an unexpected location, the retention loop can delete directories the user did not intend this skill to manage.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The script enforces retention by deleting historical run directories with rm -rf, which contradicts the skill's stated read-only posture. While it does not mutate the GitHub repository, it does perform destructive local filesystem actions that can remove cached analysis artifacts or user data if the history directory is shared or misconfigured.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script deletes prior run directories without any interactive confirmation, dry-run, or prominent warning. In an agent skill context, silent destructive behavior is more dangerous because callers may assume 'read-only' means no local state will be removed, making accidental data loss harder to notice or prevent.

Intent-Code Divergence

Low
Confidence
81% confidence
Finding
The header comment describes the script as fetching GitHub issues, detecting linked PRs, and splitting into batches, implying a preparatory/read-oriented tool. Later code silently prunes older run directories, which contradicts that stated intent by adding destructive maintenance behavior not disclosed in the documentation.

Static analysis

No suspicious patterns detected.