Back to skill

Security audit

PR Auto-Check

Security checks for vulnerabilities and agentic risk

Overview

This skill is a mostly disclosed PR-reporting helper, but it runs an unverified local health-check script and can send PR details to any supplied webhook URL.

Review before installing. Use only in repositories where PR metadata, CI status, changed-file names, and service health summaries are allowed to leave your environment. Prefer a fixed trusted health-check script path, avoid passing webhook secrets in shell history or logs, and restrict the webhook to an intended Discord endpoint.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (4)

T08 · Insecure Dependencies

Error
Location
scripts/pr_auto_check.sh:56
Finding

Untrusted Health-Check Script Discovery and Execution

Content
View full analysis
/dev/null || echo '{"max_severity":2,"checks":{}}') else # Fallback: try installed healthcheck skill HC=$(find ~/.openclaw/skills/healthcheck -name healthcheck.sh -type f 2>/dev/null | head -1) if [[ -n "$HC" ]]; then HEALTH_JSON=$(bash "$HC" --json 2>/dev/null || echo '{"max_severity":2,"checks":{}}') else HEALTH_JSON='{"max_severity":-1,"checks":{},"note":"healthcheck script not found"}' fi fi ``` ### Technical Analysis The pipeline automatically executes either a sibling `healthcheck.sh` file or the first recursively discovered file with that name under `~/.openclaw/skills/healthcheck`. It does not verify the selected script's canonical path, owner, permissions, origin, or cryptographic integrity. The fallback is particularly unsafe because `find ... | head -1` selects a script based on filesystem traversal order. If an attacker or compromised dependency can write beneath the searched directory, a counterfeit script can be selected and executed by `bash`. The sibling script is also trusted solely because it exists and is executable. The discovered script runs with the same operating-system identity, environment, filesystem access, and available credentials as the PR auto-check process. ### Attack Path 1. An attacker obtains write access to the sibling health-check location or a directory beneath `~/.openclaw/skills/healthcheck`. 2. The attacker creates a malicious file named `healthcheck.sh`. 3. The user or Agent invokes `scripts/pr_auto_check.sh`. 4. The pipeline locates the malicious file without validating its provenance. 5. The script is executed with ...[truncated 572 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/notify_discord.sh:8
Finding

Unrestricted Webhook URL Permits Server-Side Request Forgery and Report Disclosure

Content
View full analysis
--result " >&2; exit 1 fi ``` ```bash curl -s -H "Content-Type: application/json" -d "$PAYLOAD" "$WEBHOOK" >/dev/null ``` ### Technical Analysis The script describes the destination as a Discord webhook but accepts any caller-supplied URL and passes it directly to `curl`. It does not validate the URL scheme, hostname, port, or resolved address. Consequently, a caller who controls `--webhook` can direct the POST request to an attacker-controlled service or an HTTP service reachable from the Agent's network context. This includes local or private-network endpoints when they are accessible from the host. The request carries PR, CI, diff, health, and timestamp information in a Discord-style JSON payload. ### Attack Path 1. An attacker influences the command invocation or supplies the `--webhook` argument. 2. The attacker chooses an external collection endpoint or an internal HTTP service rather than a Discord webhook. 3. The script reads the designated result file and constructs a payload containing PR and health information. 4. `curl` sends the payload to the attacker-selected destination. 5. The destination receives the report, or an internal service processes the unauthorized POST request. ### Impact Assessment The direct confidentiality impact is disclosure of the report fields sent by this script, including PR identifiers, CI summaries, diff statistics, and h ...[truncated 325 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/notify_discord.sh:1
Finding

Discord Webhook Credential Exposed Through Command-Line Arguments

Content
View full analysis
--result [--channel ] set -euo pipefail WEBHOOK="" RESULT_FILE="" CHANNEL="" while [[ $# -gt 0 ]]; do case "$1" in --webhook) WEBHOOK="$2"; shift 2 ;; ``` The documented workflow directs users to pass the credential in the same manner: ```bash bash {baseDir}/scripts/notify_discord.sh --webhook --result ``` ```bash RESULT=$(bash {baseDir}/scripts/pr_auto_check.sh --pr 42 --json) && \ bash {baseDir}/scripts/notify_discord.sh --webhook "$WEBHOOK" --result "$RESULT" ``` ### Technical Analysis A Discord webhook URL contains a secret token that authorizes posting to the associated webhook. Passing the full URL as a command-line argument can expose it in process inspection interfaces, shell history, CI command logs, diagnostic output, or shell tracing. The documentation states that `DISCORD_WEBHOOK` may be set as an environment variable, but the script does not read that variable as a fallback. Even the documented one-liner expands the secret into the child process's argument vector. ### Attack Path 1. A user follows the documented invocation and supplies the webhook URL through `--webhook`. 2. The complete secret becomes part of the process argument vector and may also be retained by command history or CI logs. 3. A local observer with sufficient process-inspection access, or a party with access to retained logs, obtains the URL. 4. The observer reuses the webhook URL to submit unauthorized messages until the webhook is revoked or rotated. ### Impact Assessment An exposed webhook URL ...[truncated 338 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/pr_auto_check.sh:72
Finding

Unsafe JSON Construction Allows Report Corruption and Structure Injection

Content
View full analysis
"$RESULT_FILE" <0))'), "health": { "max_severity": $HEALTH_MAX, "summary": "$HEALTH_SUMMARY", "raw": $HEALTH_JSON } } ENDJSON ``` ### Technical Analysis The script constructs JSON through an unquoted heredoc and directly interpolates several values. `CI_SUMMARY` and `HEALTH_SUMMARY` are inserted inside JSON string literals without JSON escaping. Quotes, backslashes, newlines, or control characters in these values can make the result invalid or alter its structure. `PR_NUMBER`, `HEALTH_MAX`, and `HEALTH_JSON` are inserted as raw JSON tokens without strict validation. The PR argument is not restricted to digits, and health output is accepted from an externally executed script without validating it against the documented schema. The diff fields demonstrate the safer pattern by passing data through `jq`, but that protection is not consistently applied to the remaining fields. ### Attack Path 1. An attacker controls or influences a CI check name, CI conclusion, health-check output, or the supplied PR argument. 2. The crafted value contains JSON metacharacters, an unexpected raw value, or malformed JSON. 3. The value is interpolated directly into the heredoc. 4. The generated result file becomes invalid JSON or contains attacker-controlled structure. 5. `notify_discord.sh` or another downstream consumer fails while parsing the report or consumes manipulated fields. ### Impact Assessment The primary impact is integrity and availability loss in the reporting pipeline. ...[truncated 332 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The description claims a broader automated PR checking pipeline: execute code review, validate service health, and then notify the team. The actual code chunk is limited to the notification step. It parses an already-produced result JSON file and sends a formatted message to Discord via webhook. There is no logic to inspect a PR, run review checks, verify service health, or handle PR submission triggers. While posting to Discord is consistent with part of the description, the primary declared purpose overstates what this code chunk actually does.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The code largely implements a PR-checking/reporting utility: it inspects GitHub PR status checks, collects diff stats and changed files, invokes a healthcheck script, and formats a report. However, a key declared capability—posting the full result to a Discord channel—is absent. The script only prints output and a temp file path locally. Also, the description says 'run code review,' but the code does not review code quality/content; it only fetches CI results and diff summaries. Finally, the declared wording suggests an automated pipeline triggered on new PR submission, while this chunk is just a callable script with no trigger or event-handling logic. These are material description-to-behavior mismatches.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill invokes shell scripts but does not declare any tool restrictions or permission scope, which weakens reviewability and allows broader-than-expected command execution in environments that rely on manifest-declared boundaries. In a pipeline that handles PR data and webhooks, undeclared shell capability increases the chance of unsafe execution paths or accidental abuse.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill explicitly posts PR results to a Discord webhook, which is an external third-party endpoint, but does not require a user warning, consent step, or data minimization guidance before transmitting potentially sensitive PR metadata, CI output, or health details. In a PR-review context, this can disclose proprietary code information, internal service status, or security findings outside the trusted development boundary.

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/notify_discord.sh (reported line 56)May include surrounding context.

sh
}]
  }')

curl -s -H "Content-Type: application/json" -d "$PAYLOAD" "$WEBHOOK" >/dev/null
echo "Discord notification sent for PR #$PR"

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script falls back to locating and executing the first matching healthcheck.sh under ~/.openclaw/skills/healthcheck, which is outside the current skill package and not integrity-checked. An attacker who can place or modify files in that searched path can cause arbitrary code execution when this PR pipeline runs, and the broad find ... | head -1 selection makes the executed script nondeterministic and easy to hijack.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.