Back to skill

Security audit

Uptime Monitor

Security checks for vulnerabilities and agentic risk

Overview

The uptime skill mostly matches its stated purpose, but it can make arbitrary network requests and send service details externally without clear destination limits, so it belongs in Review before installation.

Install only if you are comfortable with the agent making outbound requests to the monitored URLs and sending alert details to your configured webhook or email. Restrict MONITOR_URLS and ALERT_WEBHOOK_URL to approved public HTTPS destinations, avoid internal hostnames or URLs containing secrets, and treat generated logs/reports as untrusted if monitored URLs can be influenced by others.

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 (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/check.sh:9
Finding
Unrestricted Outbound Requests Enable Server-Side Request Forgery<![CDATA[ ## Vulnerability Details **File Location**: `scripts/check.sh:9, 24-27`; `scripts/alert.sh:5, 37-42` **Vulnerability Type**: Server-Side Request Forgery through unvalidated curl destinations **Risk Level**: High ### Vulnerable Code ```bash # scripts/check.sh URL="${1:?Usage: $0 <url>}" CURL_OUTPUT=$(curl --silent --show-error --max-time 10 \ --write-out "%{http_code}|%{time_total}" \ --output /dev/null \ "$URL" 2>&1) ``` ```bash # scripts/alert.sh WEBHOOK_URL="${ALERT_WEBHOOK_URL:-}" if [ -n "$WEBHOOK_URL" ]; then payload=$(build_webhook_payload) response=$(curl --silent --max-time 10 \ -H "Content-Type: application/json" \ -d "$payload" \ "$WEBHOOK_URL" 2>&1) if [ $? -eq 0 ]; then echo "Alert sent to webhook for $url" else echo "Failed to send webhook alert: $response" >&2 fi fi ``` ### Technical Analysis Both scripts pass externally configurable destinations directly to `curl`. The monitoring URL is accepted as a positional argument, while the webhook destination is read from `ALERT_WEBHOOK_URL`. Neither path validates the URL scheme, hostname, resolved address, port, or destination network. Consequently, a party able to influence script arguments or environment configuration can direct requests toward resources reachable from the agent host, including: - Loopback services such as `127.0.0.1` or `[::1]`. - Private network services. - Link-local addresses and cloud metadata endpoints. - Internal administrative interfaces. - Unexpected protocols supported by the installed curl build. The health-check response body is discarded, which limits direct content disclosure, but HTTP status, timing, and success or failure can still reveal service availability. Requests may also trigger state-changing behavior if an internal endpoint performs actions on a GET request. The webhook path is more dangerous because it sends an attacker-influenced HTTP POST body. ### Attack Path 1. An attacker causes the skill to check ...[truncated 1152 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse and validate every destination before invoking `curl`. 2. Permit only the required schemes, normally HTTPS: ```bash curl --proto '=https' --proto-redir '=https' ... ``` 3. Maintain an explicit allowlist of approved monitoring and webhook hostnames. 4. Resolve destination hostnames and reject loopback, private, link-local, multicast, reserved, and cloud metadata address ranges for both IPv4 and IPv6. 5. Revalidate the resolved destination immediately before connecting to reduce DNS rebinding risk. 6. Restrict destination ports to the ports needed by the monitoring policy. 7. Run monitoring in a network sandbox that cannot access metadata endpoints or sensitive internal control-plane services. 8. Consider a centrally configured webhook destination rather than allowing per-run environment data to select it. 9. Preserve timeouts and add connection timeouts, such as `--connect-timeout`. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/alert.sh:8
Finding
Unescaped Alert Fields Permit Webhook JSON Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/alert.sh:8-11, 16-34, 38-42` **Vulnerability Type**: Improper JSON construction using unescaped shell input **Risk Level**: Medium ### Vulnerable Code ```bash url="${1:?Usage: $0 <url> <status_code> <response_time> <error_message>}" status_code="${2:-000}" response_time="${3:-N/A}" error_msg="${4:-unknown}" # Build Discord/Slack-compatible embed build_webhook_payload() { cat <<EOF { "embeds": [ { "title": "🔴 Service Down: $url", "color": 15158332, "fields": [ {"name": "URL", "value": "$url", "inline": true}, {"name": "Status Code", "value": "$status_code", "inline": true}, {"name": "Response Time", "value": "$response_time", "inline": true}, {"name": "Error", "value": "$error_msg", "inline": false} ], "timestamp": "$timestamp" } ] } EOF } if [ -n "$WEBHOOK_URL" ]; then payload=$(build_webhook_payload) response=$(curl --silent --max-time 10 \ -H "Content-Type: application/json" \ -d "$payload" \ "$WEBHOOK_URL" 2>&1) fi ``` ### Technical Analysis The script creates JSON through an unquoted here-document and directly interpolates the URL, status code, response time, and error message. Shell quoting around the final `-d "$payload"` argument does not perform JSON escaping. An input containing a double quote, backslash, newline, control character, or JSON fragment can terminate the intended string or alter the structure of the generated payload. At minimum, this can produce invalid JSON and suppress legitimate alerts. Depending on the webhook receiver's schema and behavior, a crafted value can add or manipulate fields and notification content. This issue is JSON/data injection rather than shell command injection: the values are not evaluated as shell syntax after expansion. Nevertheless, they cross the JSON serialization boundary without appropriate encoding. ### Attack Path 1. An attacker influences one ...[truncated 948 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Construct JSON with a serializer instead of string interpolation. For example: ```bash payload=$(jq -n \ --arg url "$url" \ --arg status_code "$status_code" \ --arg response_time "$response_time" \ --arg error "$error_msg" \ --arg timestamp "$timestamp" \ '{ embeds: [{ title: ("🔴 Service Down: " + $url), color: 15158332, fields: [ {name: "URL", value: $url, inline: true}, {name: "Status Code", value: $status_code, inline: true}, {name: "Response Time", value: $response_time, inline: true}, {name: "Error", value: $error, inline: false} ], timestamp: $timestamp }] }') ``` Also: 1. Validate status codes and response-time values against strict formats. 2. Reject or normalize control characters where they are not needed. 3. Apply maximum lengths to all alert fields. 4. Check the webhook's HTTP status rather than treating any successful curl transport as a successfully accepted alert. 5. Declare `jq` as a required dependency if it is adopted. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/check.sh:35
Finding
Unescaped URL Data Enables Log Forgery and Report Injection<![CDATA[ ## Vulnerability Details **File Location**: `scripts/check.sh:35-50`; `scripts/alert.sh:69-72`; `scripts/report.sh:22-31, 51-58, 73-81` **Vulnerability Type**: Log injection, regular-expression injection, and Markdown injection **Risk Level**: Medium ### Vulnerable Code ```bash # scripts/check.sh if [ $curl_exit -ne 0 ]; then echo "FAIL|$URL|000|curl_error:$curl_exit" echo "$(date -u +%Y-%m-%dT%H:%M:%SZ)|$URL|FAIL|000|$curl_exit" >> "$LOG_DIR/status.log" exit 1 fi if [[ "$status_code" =~ ^[0-9]{3}$ ]] && [ "$status_code" -ge 200 ] && [ "$status_code" -lt 400 ]; then echo "OK|$URL|$status_code|${time_total}s" echo "$(date -u +%Y-%m-%dT%H:%M:%SZ)|$URL|OK|$status_code|${time_total}s" >> "$LOG_DIR/status.log" exit 0 else echo "FAIL|$URL|$status_code|http_error" echo "$(date -u +%Y-%m-%dT%H:%M:%SZ)|$URL|FAIL|$status_code|http_error" >> "$LOG_DIR/status.log" exit 1 fi ``` ```bash # scripts/alert.sh LOG_DIR="$(dirname "$0")/../logs" mkdir -p "$LOG_DIR" echo "$(date -u +%Y-%m-%dT%H:%M:%SZ)|$url|ALERT_SENT|$status_code|$error_msg" >> "$LOG_DIR/alerts.log" ``` ```bash # scripts/report.sh urls=$(cut -d'|' -f2 "$LOG_FILE" | sort -u) for url in $urls; do checks=$(grep "|${url}|" "$LOG_FILE" | grep -v "^${cutoff_date}" | wc -l) up_checks=$(grep "|${url}|OK|" "$LOG_FILE" | grep -v "^${cutoff_date}" | wc -l) # ... echo "## $status $url" echo "" echo "| Metric | Value |" echo "|--------|-------|" echo "| Total Checks | $checks |" echo "| Successful | $up_checks |" echo "| Downtime | $((checks - up_checks)) |" echo "| Uptime | ${uptime_pct}% |" done tail -10 "$ALERT_LOG" | while read -r line; do echo "- \`$line\`" done ``` ### Technical Analysis The scripts use pipe-delimited plain-text logs but do not escape or reject delimiter characters, carriage returns, or newlines in attacker-influenced fields. A crafted URL or error message can therefore create additional apparent records or shift fields within a record. The r ...[truncated 1943 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace ad hoc pipe-delimited logs with structured records, preferably one JSON object per line, generated by a real JSON serializer. 2. Reject carriage returns, newlines, NUL bytes, and other control characters in URLs and alert fields before logging. 3. If the pipe-delimited format must remain, encode every field and decode it only through a dedicated parser. 4. Avoid treating URL data as a regular expression. Use fixed-string matching where appropriate: ```bash grep -F -- "|${url}|" "$LOG_FILE" ``` Structured parsing is preferable because fixed-string matching alone does not solve delimiter ambiguity. 5. Read URLs without shell word splitting: ```bash while IFS= read -r url; do # Process one complete URL. done < <(cut -d'|' -f2 "$LOG_FILE" | sort -u) ``` 6. Escape Markdown metacharacters before rendering URLs and alert records. 7. Apply strict URL syntax and length validation at input time. 8. Protect log files with restrictive permissions and ensure only the monitoring account can modify them. 9. Correct the date filtering logic using parsed timestamps rather than `grep -v`, which only excludes records matching a text prefix and does not reliably select records newer than the cutoff. ]]>
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 (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The documented purpose emphasizes uptime monitoring, but the described behavior also includes outbound webhook delivery, email transmission, and local logging. This mismatch can mislead users or automated systems into approving a skill with broader data egress and persistence behavior than expected, creating risk of unreviewed disclosure of service metadata.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill declares shell-capable behavior but does not define any explicit tool scope or permissions boundaries. In an agent environment, this increases the chance of unintended command execution or broader-than-necessary access because the runtime and reviewer cannot easily constrain what the skill is allowed to do.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The documentation states that alerts may be sent to webhook or email destinations without explicitly warning that service status, URLs, error details, or internal endpoint information may be transmitted to external parties. In operational environments, this can expose sensitive infrastructure metadata or incident details through third-party channels without informed user consent.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
This code transmits operational data, including the monitored URL, status code, response time, and error message, to an external webhook endpoint. Although the script logs success or failure afterward, it does not clearly disclose before or at configuration time that these details will be sent off-host via the ALERT_WEBHOOK_URL setting.

External Transmission

Medium
Category
Data Exfiltration
Content
# Send webhook alert if configured
if [ -n "$WEBHOOK_URL" ]; then
  payload=$(build_webhook_payload)
  response=$(curl --silent --max-time 10 \
    -H "Content-Type: application/json" \
    -d "$payload" \
    "$WEBHOOK_URL" 2>&1)
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Vague Triggers

Low
Confidence
90% confidence
Finding
The description says to use the skill when 'checking if a website is reachable' or 'monitoring service health,' which are broad natural-language conditions without explicit trigger boundaries or exclusions. In a manifest/markdown context, this can cause unintended invocation overlap with other diagnostics or networking skills.

Static analysis

No suspicious patterns detected.