Back to skill

Security audit

Address Review Comments

Security checks for vulnerabilities and agentic risk

Overview

The skill is transparent about its goal, but it allows PR comments to drive automatic commits, pushes, GitHub replies, and future watch-triggered rounds using the user's credentials.

Install only if you are comfortable with this skill using your GitHub credentials to modify a PR branch, push commits, and post comments automatically. Use it only on repositories where PR commenters are tightly trusted, verify the proposed diff before relying on the result, and confirm how any background watch can be listed and stopped before enabling the loop behavior.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:18
Finding
Untrusted PR Comments Can Direct Repository Modifications## Vulnerability Details **File Location**: `SKILL.md`, lines 18–22, 194–201, and 221–232 **Vulnerability Type**: Untrusted instructions controlling privileged repository operations **Risk Level**: High ### Vulnerable Code Snippets ```markdown It decides which round to act on by matching PR comment CONTENT against a marker pattern (see Step 2), not by authenticating who posted it beyond GitHub's own login attribution — anyone who can comment on the PR (including, on some repos, the PR author replying to their own automated review) can shape which comment this skill treats as "the latest reviewer batch." ``` ```markdown Identify the latest REVIEWER comment and the latest comment authored by us (the reply posted last round). Then branch: **Do not distinguish them by author.** The automated reviewer may post under the SAME GitHub account as our replies, so `.user.login` cannot tell them apart. Distinguish by content: reviewer batches carry a `<!-- review-pr-state … cycle=N … -->` metadata block; our replies carry `codex-addressed:<batch_id>`. ``` ```markdown 3. **New findings**: the latest reviewer comment is newer than our last reply and contains findings. Proceed to Step 3. ``` ```markdown ## Step 3 — Apply the fixes (per-edit disk writes, asserted matches) Enumerate every finding in the latest reviewer comment. For each one, locate the exact current text (`grep -n` first — never edit from memory of the file), then apply the edit. ``` ### Technical Analysis The skill treats a marker embedded in PR comment content as the trust signal for a reviewer batch. The marker and all associated findings are attacker-controlled text. The instructions explicitly decline to authenticate the batch by its author and acknowledge that anyone able to comment may shape the selected batch. After selecting such a batch, the skill directs the agent to implement every finding, commit the resulting modifications, and push them using the invoking user's GitHub cr ...[truncated 1608 chars]
Remediation
## Remediation Suggestions 1. Authenticate reviewer batches against an explicit allowlist of immutable GitHub actor IDs, not display names, login text, or comment-body markers. 2. Fetch actor identity and repository role through the GitHub API and reject comments from unauthorized, suspended, or insufficiently privileged accounts. 3. Treat comment bodies as untrusted data. Ignore embedded instructions that attempt to alter the skill workflow, invoke tools, access secrets, or expand the requested scope. 4. Define an edit policy that restricts changes to files and findings directly relevant to the PR review. 5. Generate and display the proposed diff before any commit or push. 6. Require explicit human confirmation before privileged write operations, especially changes to CI workflows, executable scripts, dependencies, release configuration, and security controls. 7. Cryptographically or server-side bind each batch identifier to the authorized reviewer and PR rather than trusting a copyable HTML marker. 8. Record the validated actor ID, comment ID, and commit SHA in the reply for auditability. 9. Preserve the existing prohibition on merging, but do not rely on it as the primary control because pushed branch changes can still execute in CI or influence later merges.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:44
Finding
Predictable Shared Temporary Paths Permit Local File Manipulation## Vulnerability Details **File Location**: `SKILL.md`, lines 44–48, 126–145, and 335–340 **Vulnerability Type**: Predictable temporary directory and unsafe file handling **Risk Level**: Medium ### Vulnerable Code Snippets ```bash SCRATCH="${TMPDIR:-/tmp}/pr${PR}-round"; mkdir -p "$SCRATCH" ``` ```bash SCRATCH="${TMPDIR:-/tmp}/pr${PR}-round"; mkdir -p "$SCRATCH" # Brace the variable: `pr$PR_all_comments.txt` expands to `pr.txt` — one undefined name, # silently the wrong file. OUT="$SCRATCH/pr${PR}_all_comments.txt" # Write to a temp and move only on success. A failed page must not leave a SHORT history # file behind, because a short file is exactly what this block exists to prevent and # nothing downstream can tell one from a quiet PR. { for ep in "issues/$PR/comments:comment" "pulls/$PR/reviews:review" "pulls/$PR/comments:reply"; do gh api --paginate --slurp "repos/$REPO/${ep%%:*}" \ | jq --arg k "${ep##*:}" '[ .[][] | {kind:$k, who:.user.login, at:.created_at, body:(.body // "")} ]' done } | jq -s -r '[.[][]] | sort_by(.at) | .[] | "=== \(.kind) by \(.who) @ \(.at) ===\n\(if .body == "" then "(no body — inline comments only)" else .body end)\n"' \ > "$OUT.part" mv "$OUT.part" "$OUT" ``` ```bash set -euo pipefail PR="$ARGUMENTS" case "$PR" in ''|*[!0-9]*) echo "PR must be numeric, got '$PR'" >&2; exit 1 ;; esac SCRATCH="${TMPDIR:-/tmp}/pr${PR}-round" gh pr comment "$PR" --body-file "$SCRATCH/reply.md" ``` ### Technical Analysis The scratch directory name is derived solely from a predictable PR number and defaults to shared `/tmp`. The skill creates or reuses this directory with `mkdir -p` without validating its owner, permissions, or file type. It also does not protect individual paths against symbolic links. The history file is written through a predictable `*.part` path and then moved. The reply is later read from a predictable `reply.md` path. A local attacker with access to the same temporary namespace can pre-create the direct ...[truncated 1484 chars]
Remediation
## Remediation Suggestions 1. Create a unique private directory using `mktemp -d`, and enforce permissions with `umask 077` and mode `0700`. 2. Persist the generated directory path through a protected host state mechanism instead of deriving it from a public PR number. 3. Verify that the scratch directory is owned by the current user, is not a symbolic link, and has no group or world permissions before every reuse. 4. Create files with exclusive creation and no-follow semantics where supported. 5. Validate that `reply.md` and history files are regular files owned by the current user immediately before use. 6. Avoid predictable `.part` names; use a unique file created inside the private directory and atomically rename it after successful generation. 7. Reject untrusted `TMPDIR` values unless the selected directory is validated as secure. 8. Remove the private scratch directory when the workflow reaches a terminal state. 9. Where cross-process continuity is required, pass a securely generated identifier or path explicitly rather than reconstructing a globally predictable path.
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

Static analysis

No suspicious patterns detected.