Back to skill

Security audit

Apollo Issue Review

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent for GitHub issue triage, but needs review because its publish commands can mishandle untrusted reply text and GitHub credentials.

Use draft-only mode by default. If enabling posting, require an explicit final review of the exact repository, issue number, and comment body, use scoped GitHub credentials, and replace the raw placeholder commands with structured `gh api --input` or serializer-produced JSON so issue text cannot become shell syntax.

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
SKILL.md:129
Finding
Unsafe Shell and JSON Interpolation of Untrusted Reply Content<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 129–138 **Vulnerability Type**: Command injection and malformed JSON caused by unsafe interpolation **Risk Level**: Medium ### Vulnerable Code ```bash gh api repos/<owner>/<repo>/issues/<id>/comments -f body='<reply>' ``` ```bash TOKEN=$(gh auth token) curl --http1.1 -sS -X POST \ -H "Authorization: token $TOKEN" \ -H "Accept: application/vnd.github+json" \ -d '{"body":"<reply>"}' \ https://api.github.com/repos/<owner>/<repo>/issues/<id>/comments ``` ### Technical Analysis The documented publication commands interpolate the generated `<reply>` directly into shell-quoted arguments and manually constructed JSON. The reply is derived from GitHub issue titles, bodies, and comments, which are attacker-controlled inputs. In the `gh api` command, an apostrophe in the reply can terminate the single-quoted shell argument. If the agent implements the example through textual substitution and passes the result to a shell, subsequent attacker-controlled characters may be interpreted as shell syntax. In the `curl` fallback, the reply is inserted into a manually assembled JSON string without JSON encoding. Double quotes, backslashes, control characters, or newlines can invalidate or alter the request body. Shell quoting can also be disrupted depending on how placeholders are substituted. The Skill includes an explicit publication confirmation gate, which reduces exposure but does not eliminate the vulnerability: approval authorizes publication of the visible reply, not execution of shell syntax embedded in it. ### Attack Path 1. An attacker creates or comments on an Apollo GitHub issue using text containing crafted quotation marks and shell metacharacters. 2. The Skill reads that untrusted issue content and incorporates some of it into the proposed maintainer reply. 3. A maintainer reviews the rendered reply and explicitly approves publication. 4. The agent replaces `<reply>` in one of th ...[truncated 1149 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not interpolate generated replies into shell command strings. Invoke `gh` or `curl` through a structured process API with a separate argument array and without `shell=true`. 2. Encode request bodies with a real JSON serializer. For example: ```bash payload_file=$(mktemp) trap 'rm -f "$payload_file"' EXIT jq -n --arg body "$reply" '{body: $body}' > "$payload_file" gh api "repos/$owner/$repo/issues/$issue_id/comments" \ --method POST \ --input "$payload_file" ``` 3. If `curl` is required, pass only serializer-produced JSON: ```bash payload=$(jq -n --arg body "$reply" '{body: $body}') curl --http1.1 -sS -X POST \ -H "Authorization: Bearer $TOKEN" \ -H "Accept: application/vnd.github+json" \ -H "Content-Type: application/json" \ --data-binary "$payload" \ "https://api.github.com/repos/$owner/$repo/issues/$issue_id/comments" ``` 4. Validate repository coordinates before use: - Owner and repository names must match an allowlisted GitHub identifier pattern. - The issue ID must contain digits only. - Prefer restricting publication to the repository supplied through trusted configuration. 5. Treat issue titles, bodies, comments, and generated replies explicitly as untrusted data. Never evaluate them as commands, templates, or instructions. 6. Keep the existing explicit publication gate, and additionally show the final repository, issue number, and exact rendered comment before execution. 7. Avoid exposing the token as an ordinary shell variable when possible. Prefer authenticated `gh api` execution so token handling remains within the GitHub CLI. ]]>
Vulnerability Patterns
  • 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
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (5)

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The instruction says to match the issue language, specifying English issues get English replies and Chinese issues get Chinese replies unless the user explicitly asks for bilingual output. This imposes a language policy by default rather than offering the operator or user a language choice, which fits the locale/language policy violation category.

External Transmission

Medium
Category
Data Exfiltration
Content
- Normalize names to canonical module/service terms used by Apollo repo (e.g., `apollo-portal`, not invented service names).
- If GitHub API access is unstable, use:
```bash
curl -L -s https://api.github.com/repos/<owner>/<repo>/issues/<id>
curl -L -s https://api.github.com/repos/<owner>/<repo>/issues/<id>/comments
```
Confidence
82% confidence
Finding
The skill instructs the agent to fetch issue data directly from GitHub over the network. External transmission is risky in an agent setting because issue content is untrusted input, and automatic retrieval can enlarge the attack surface by importing adversarial content and enabling unintended data flow to third-party services. In this case the destination is legitimate GitHub infrastructure, which lowers concern, but the network action is still a real capability that should be gated.

External Transmission

Medium
Category
Data Exfiltration
Content
- If GitHub API access is unstable, use:
```bash
curl -L -s https://api.github.com/repos/<owner>/<repo>/issues/<id>
curl -L -s https://api.github.com/repos/<owner>/<repo>/issues/<id>/comments
```

2. Run the right validation path (mandatory)
Confidence
82% confidence
Finding
This is another direct GitHub API retrieval path for issue comments, which imports additional untrusted external content into the agent workflow. While reading comments is central to the skill’s function, automatic outbound access can still be abused in environments where network operations require tighter review or where imported content can influence later actions.

External Transmission

Medium
Category
Data Exfiltration
Content
- Fallback when `gh` transport is unstable:
```bash
TOKEN=$(gh auth token)
curl --http1.1 -sS -X POST \
  -H "Authorization: token $TOKEN" \
  -H "Accept: application/vnd.github+json" \
  -d '{"body":"<reply>"}' \
Confidence
97% confidence
Finding
The skill includes a fallback that extracts an auth token with `gh auth token` and uses it in a raw `curl` POST to publish a comment. This is dangerous because it operationalizes credential use inside the skill and can cause unintended authenticated actions or token exposure through logs, shell history, subprocess inspection, or prompt-influenced misuse. The mandatory confirmation gate helps, but does not eliminate the risk of credential handling embedded in the skill.

External Transmission

Medium
Category
Data Exfiltration
Content
-H "Authorization: token $TOKEN" \
  -H "Accept: application/vnd.github+json" \
  -d '{"body":"<reply>"}' \
  https://api.github.com/repos/<owner>/<repo>/issues/<id>/comments
```
- After posting, return the comment URL as evidence.
Confidence
88% confidence
Finding
This line is the authenticated POST destination for publishing a GitHub issue comment. Posting externally is a real side-effecting capability; if the draft is manipulated by untrusted issue content or approval checks fail open, the agent could publish unintended content to a public repository. The surrounding workflow reduces risk by requiring explicit confirmation, but the action remains security-relevant.

Static analysis

No suspicious patterns detected.