Back to skill

Security audit

PR Automate Check

Security checks for vulnerabilities and agentic risk

Overview

This PR automation skill is coherent, but it should be reviewed because it runs authenticated GitHub commands, can execute a local helper script, and can send PR and health data to an arbitrary webhook without strong safeguards.

Review before installing. Use it only in trusted repositories with scoped GitHub credentials, pass only an approved Discord webhook, avoid feeding webhook URLs from untrusted automation, and verify the local healthcheck skill before letting this run automatically from cron or PR events.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (5)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/pr-check.sh:74
Finding

Arbitrary Webhook Destination Enables SSRF and Information Disclosure

Content
View full analysis

Vulnerability Details

File Location: scripts/pr-check.sh:74-85
Vulnerability Type: Unrestricted outbound request / SSRF
Risk Level: High

bash
payload=$(jq -n \
  --arg ts "$ts" \
  --arg pr "$PR_URL" \
  --arg health "$health_summary" \
  '{
    embeds: [{
      title: ("PR Auto-Check: " + $pr),
      color: (if ($health | test("✅")) then 3066993 elif ($health | test("⚠️")) then 16776960 else 15158332 end),
      fields: [
        {name: "Health Check", value: $health, inline: false},
        {name: "PR", value: $pr, inline: false}
      ],
      footer: {text: ("Reported at " + $ts)}
    }]
  }')

curl -sS -X POST "$DISCORD_WEBHOOK" \
  -H 'Content-Type: application/json' \
  -d "$payload" > /dev/null 2>&1 || echo "Discord webhook failed"

Technical Analysis

The second command-line argument is documented as a Discord webhook, but the script passes it directly to curl without validating its scheme, hostname, port, resolved IP address, or destination type. Consequently, the caller can cause the process to send an HTTP POST request to any URL reachable from the execution environment.

The transmitted payload contains the supplied PR URL and health-check information. If the script operates inside a trusted network, the request can target loopback, link-local, private-network, or internal service addresses. Suppression of the response body does not prevent state-changing requests or establish that the destination is safe.

Attack Path

  1. An attacker or untrusted automation supplies a URL such as an internal service endpoint as the second argument.
  2. The script performs the PR and health checks and constructs a JSON payload.
  3. curl sends the payload to the attacker-selected endpoint.
  4. The endpoint receives repository and health information, or the POST request triggers an internal operation accessible from the execution environment.

Impact Assessment

...[truncated 395 chars]

Remediation
View remediation

Remediation Suggestions

  • Parse the destination URL before invoking curl.
  • Require HTTPS and allow only explicitly approved Discord webhook hostnames and URL paths.
  • Resolve the hostname and reject loopback, link-local, private, multicast, and other non-public address ranges, including after DNS resolution.
  • Disable redirects with --max-redirs 0, or independently validate every redirect target.
  • Store the webhook in trusted configuration or a secret manager instead of accepting it from untrusted task input.
  • Apply outbound firewall or proxy allowlisting as defense in depth.
  • Avoid including sensitive health details in notifications unless they are required.

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:32
Finding

Untrusted Pull Request Diff Can Inject Instructions into the Agent Review Context

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:32
Vulnerability Type: Indirect prompt injection
Risk Level: High

text
The script extracts the PR number, fetches the diff and CI status via `gh`, and writes them to a temp directory. The agent then reads the diff and performs a structured review following the code-review skill's guidelines (quality, security, performance, test coverage).

Technical Analysis

Pull request diffs are controlled by PR contributors and may contain natural-language instructions in source files, documentation, comments, tests, or filenames. The Skill directs the Agent to read this content but does not state that the diff is untrusted data or prohibit the Agent from following instructions embedded in it.

This creates an indirect prompt-injection boundary failure: data intended for analysis is placed in the Agent's context without isolation from trusted task instructions. An attacker can attempt to redefine the review objective, suppress security findings, manipulate the report, or induce unrelated tool activity.

Attack Path

  1. An attacker opens a pull request containing text that instructs an AI reviewer to ignore its original task, conceal findings, or perform an attacker-selected action.
  2. gh pr diff retrieves the attacker-controlled content and writes it to diff.txt.
  3. Following SKILL.md, the Agent reads the diff to conduct the review.
  4. Without explicit data-boundary safeguards, the embedded text may be interpreted as an instruction rather than content under review.
  5. The review output or subsequent Agent behavior may be altered.

Impact Assessment

The immediate impact is loss of integrity and reliability of the security review, including false negatives and misleading approval recommendations. If the reviewing Agent has access to tools, credentials, files, or network operations, successful injection could also attempt to misuse those capabilities withi ...[truncated 139 chars]

Remediation
View remediation

Remediation Suggestions

  • Explicitly declare all PR metadata, diffs, source files, comments, and generated output to be untrusted data.
  • Instruct the Agent never to execute or follow instructions found in reviewed content.
  • Delimit untrusted material clearly and require the Agent to treat it solely as an analysis subject.
  • Use a structured review workflow that extracts file changes and findings rather than placing an unrestricted raw diff into the instruction context.
  • Require confirmation before any tool operation not strictly necessary for reading repository data.
  • Run review agents with minimal filesystem, network, credential, and command-execution permissions.
  • Add adversarial prompt-injection tests to the Skill's validation suite.

T07 · Tool Hijacking and Spoofing

Error
Location
scripts/pr-check.sh:30
Finding

Mutable User-Directory Health-Check Script Is Executed Without Integrity Verification

Content
View full analysis

Vulnerability Details

File Location: scripts/pr-check.sh:30-32
Vulnerability Type: Unverified local tool execution
Risk Level: High

bash
if command -v bash &>/dev/null && [[ -f ~/.openclaw/skills/healthcheck/healthcheck.sh ]]; then
  bash ~/.openclaw/skills/healthcheck/healthcheck.sh --json > "$health_file" 2>/dev/null || \
    echo '{"max_severity":2,"checks":{}}' > "$health_file"

Technical Analysis

The Skill automatically executes a script at a predictable path under the current user's home directory. It verifies only that the path references a regular file. It does not verify ownership, file or parent-directory permissions, provenance, version, cryptographic integrity, or whether symbolic-link/path manipulation has occurred.

Any party or compromised component able to create or replace this file can cause arbitrary shell commands to run when the PR check is invoked. The health-check output redirection and fallback do not constrain commands executed by the dependency.

Attack Path

  1. An attacker gains write access to ~/.openclaw/skills/healthcheck/healthcheck.sh or a relevant parent directory.
  2. The attacker creates or replaces the script with commands of their choice.
  3. A user or automation invokes pr-check.sh.
  4. The existence test succeeds, and Bash executes the attacker-controlled file.
  5. The payload runs with the filesystem, process, credential, and network permissions of the Skill process.

Impact Assessment

Successful exploitation provides arbitrary command execution under the account running the Skill. The attacker could read or modify files available to that account, access inherited environment variables and credentials, make network requests, alter review results, or tamper with other user-owned tools. Root-level compromise is possible only if the Skill itself is run with root or equivalent privileges.

Remediation
View remediation

Remediation Suggestions

  • Use a dependency installed from a trusted, version-pinned source rather than automatically executing a mutable script discovered in the home directory.
  • Verify expected ownership, restrictive permissions, and safe permissions on every parent directory.
  • Validate the dependency against a pinned cryptographic digest or trusted signature before execution.
  • Reject symbolic links and resolve the canonical path before applying security checks.
  • Execute the health check in a sandbox with minimal filesystem, network, and credential access.
  • Prefer a narrowly defined data interface over arbitrary shell-script execution.
  • Fail closed when dependency authenticity cannot be established.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/pr-check.sh:44
Finding

Unescaped Values Allow JSON Report Injection and Corruption

Content
View full analysis

Vulnerability Details

File Location: scripts/pr-check.sh:44-52
Vulnerability Type: Improper JSON construction and output injection
Risk Level: Medium

bash
ts=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
cat > "$tmpdir/report.json" <<REPORT
{
  "timestamp": "$ts",
  "pr_url": "$PR_URL",
  "pr_number": "$PR_NUM",
  "health": $(cat "$health_file"),
  "review_diff_path": "$tmpdir/diff.txt"
}
REPORT

Technical Analysis

The report is assembled through raw shell interpolation rather than a JSON encoder. PR_URL is inserted into a quoted JSON string without escaping quotation marks, backslashes, control characters, or newlines. The entire health-check output is also inserted as a JSON value without first validating that it is valid JSON or conforms to the expected schema.

A crafted input can therefore produce invalid JSON or inject additional properties. A compromised or defective health-check dependency can similarly alter the surrounding report structure. Shell command substitution does not execute shell syntax contained in the resulting output, so the direct issue is report injection and integrity loss rather than command injection.

Attack Path

  1. An attacker supplies a crafted first argument containing JSON metacharacters while retaining a /pull/&lt;number> substring, or controls the output of the optional health-check script.
  2. The script interpolates the value directly into the report heredoc.
  3. The resulting file becomes malformed or contains attacker-selected JSON fields and values.
  4. A downstream Agent or parser consumes the corrupted report and may receive falsified PR or health information.

Impact Assessment

Exploitation can compromise report integrity, cause downstream parsing failures, and falsify fields used in review summaries or automated decisions. It does not directly execute operating-system commands. The affected scope includes consumers of the generated report and ...[truncated 59 chars]

Remediation
View remediation

Remediation Suggestions

  • Construct the complete report with jq, passing strings through --arg and validated JSON through --argjson.
  • Validate health-check output with jq -e before using it.
  • Enforce a strict health schema, including the type and permitted range of max_severity and the expected shape of checks.
  • Reject invalid input rather than embedding fallback text into a structured report.
  • Treat every external command's output as untrusted data.
  • Add tests covering quotation marks, backslashes, newlines, control characters, malformed JSON, and injected object properties.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/pr-check.sh:15
Finding

Weak Pull Request URL Validation Can Associate Results with the Wrong Repository

Content
View full analysis

Vulnerability Details

File Location: scripts/pr-check.sh:15-18
Vulnerability Type: Improper input validation and repository context confusion
Risk Level: Medium

bash
# Extract PR number from URL (supports github.com/owner/repo/pull/123)
if [[ "$PR_URL" =~ /pull/([0-9]+) ]]; then
  PR_NUM="${BASH_REMATCH[1]}"
  gh pr diff "$PR_NUM" > "$tmpdir/diff.txt" 2>/dev/null || echo "diff-unavailable" > "$tmpdir/diff.txt"
  gh pr view "$PR_NUM" --json title,author,statusCheckRollup > "$tmpdir/pr-meta.json" 2>/dev/null || '{}'

Technical Analysis

The documentation requires a GitHub pull request URL, but the implementation accepts any string containing /pull/ followed by digits. It does not validate the scheme, hostname, owner, repository, complete path, or trailing content.

After extracting only the numeric identifier, the script invokes gh pr diff and gh pr view without specifying a repository. Those commands therefore depend on ambient GitHub CLI or current-directory repository context. The displayed and reported URL can refer to one repository while the retrieved diff and metadata originate from another repository with the same PR number.

Attack Path

  1. An attacker supplies a deceptive or non-GitHub string containing /pull/123.
  2. The script extracts 123 and discards the purported owner and repository.
  3. GitHub CLI resolves PR 123 using the execution environment's ambient repository context.
  4. The script reports the attacker-supplied URL while reviewing data from the ambient repository.
  5. Users or automation may rely on a review or health notification associated with the wrong pull request.

Impact Assessment

This issue undermines the integrity of the review pipeline and can lead to incorrect approval decisions, misleading Discord notifications, or unintended exposure of metadata from another accessible repository. Access remains constrained by the GitHub CLI credentials alrea ...[truncated 89 chars]

Remediation
View remediation

Remediation Suggestions

  • Strictly parse and validate the complete URL as https://github.com/{owner}/{repository}/pull/{number}.
  • Reject user information, fragments, unexpected query parameters, alternate schemes, non-GitHub hosts, malformed path segments, and trailing content.
  • Pass the validated full PR URL directly to gh, or invoke gh with an explicit --repo owner/repository argument.
  • Retrieve canonical PR metadata and verify that its repository, number, and URL match the validated input before continuing.
  • Include canonical repository identity in the generated report.
  • Fail closed if repository context cannot be established unambiguously.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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 (5)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The documented behavior omits important capabilities: GitHub access via gh, outbound webhook delivery to Discord, and execution of an external healthcheck script from the local filesystem. This mismatch is dangerous because it hides network and code-execution behavior from users and policy systems, which can lead to unauthorized data disclosure or execution of unreviewed local components.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill clearly directs execution of shell commands and external scripts, but it declares no tool scope or permissions boundaries. This is dangerous because an agent may invoke shell, networked CLIs, and local dependencies without explicit authorization, increasing the chance of unintended code execution or data access.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The manifest description lists activation phrases such as "PR check" and especially "auto review," which are broad enough to match routine conversation outside this specific skill. The file does not provide exclusion conditions or negative examples to clarify when the skill should not activate.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill describes Discord notification behavior but does not clearly warn that PR-related data will be transmitted to an external webhook endpoint. This is dangerous because PR metadata, review context, or health information may be sent outside the trusted environment without informed user consent, creating confidentiality and compliance risks.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
70% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · scripts/pr-check.sh (reported line 83)May include surrounding context.

sh
}]
    }')

  curl -sS -X POST "$DISCORD_WEBHOOK" \
    -H 'Content-Type: application/json' \
    -d "$payload" > /dev/null 2>&1 || echo "Discord webhook failed"
fi

Static analysis

No suspicious patterns detected.