Back to skill

Security audit

Site Health Monitor

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly does what it says, but it can make unrestricted network checks from the agent host and its SSL result can give false assurance.

Install only if you are comfortable with the agent making network requests to user-provided targets. Avoid checking localhost, private network names/IPs, or cloud metadata addresses, and do not rely on the SSL status as proof that a certificate is trusted or matches the hostname until validation is fixed.

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

Warning
Location
scripts/check_site.sh:8
Finding

Unrestricted Network Targets Enable Server-Side Request Forgery and Internal Service Probing

Content
View full analysis
}" # Ensure URL has scheme if [[ ! "$URL" =~ ^https?:// ]]; then URL="https://$URL" fi # Create temp file for headers HEADER_FILE=$(mktemp) trap 'rm -f "$HEADER_FILE"' EXIT # Perform the request with timing HTTP_CODE=$(curl -s -o /dev/null -w '%{json}' \ --max-time 15 \ --connect-timeout 10 \ -D "$HEADER_FILE" \ -L \ "$URL" 2>/dev/null) || { echo "{\"url\":\"$URL\",\"status\":\"error\",\"status_code\":0,\"error\":\"Connection failed or timed out\",\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" exit 0 } ``` From `scripts/check_ssl.sh`: ```bash DOMAIN="${1:?Usage: check_ssl.sh }" # Strip protocol and path if provided DOMAIN=$(echo "$DOMAIN" | sed -E 's|^https?://||' | sed 's|/.*||' | sed 's|:.*||') # Get certificate info CERT_INFO=$(echo | openssl s_client -servername "$DOMAIN" -connect "$DOMAIN:443" 2>/dev/null) || { echo "{\"domain\":\"$DOMAIN\",\"status\":\"error\",\"error\":\"Could not connect to $DOMAIN:443\",\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" exit 0 } ``` ### Technical Analysis Both scripts accept an arbitrary destination without checking whether the resolved address is public. They do not reject loopback, private, link-local, reserved, multicast, or cloud-metadata address ranges. The HTTP implementation additionally uses `curl -L`, which follows redirects. Consequently, validating only the initial URL would still be insufficient: a public attacker-controlled endpoint could redirect the request to an internal address. The HTTP response body is discarded, which limits direct data extraction. However, the script still discloses response status, timing, redirect information, eff ...[truncated 1684 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/check_site.sh:45
Finding

Externally Controlled Values Are Interpolated into JSON Without Escaping

Content
View full analysis
/dev/null || echo "$URL") # Determine status if [[ "$STATUS_CODE" -ge 200 && "$STATUS_CODE" -lt 400 ]]; then STATUS="up" elif [[ "$STATUS_CODE" -ge 400 && "$STATUS_CODE" -lt 500 ]]; then STATUS="warning" elif [[ "$STATUS_CODE" -ge 500 ]]; then STATUS="down" else STATUS="error" fi # Extract server header SERVER=$(grep -i "^server:" "$HEADER_FILE" | tail -1 | sed 's/^[Ss]erver: *//' | tr -d '\r\n' || echo "unknown") # Output JSON cat <
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/check_ssl.sh:14
Finding

TLS Certificate Status Is Reported Without Chain or Hostname Verification

Content
View full analysis
/dev/null) || { echo "{\"domain\":\"$DOMAIN\",\"status\":\"error\",\"error\":\"Could not connect to $DOMAIN:443\",\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" exit 0 } # Extract certificate details CERT_TEXT=$(echo "$CERT_INFO" | openssl x509 -noout -dates -issuer -subject 2>/dev/null) || { echo "{\"domain\":\"$DOMAIN\",\"status\":\"error\",\"error\":\"Could not parse certificate\",\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" exit 0 } # Parse dates NOT_BEFORE=$(echo "$CERT_TEXT" | grep "notBefore=" | cut -d= -f2-) NOT_AFTER=$(echo "$CERT_TEXT" | grep "notAfter=" | cut -d= -f2-) ISSUER=$(echo "$CERT_TEXT" | grep "issuer=" | sed 's/^issuer= *//') SUBJECT=$(echo "$CERT_TEXT" | grep "subject=" | sed 's/^subject= *//') # Calculate days until expiry EXPIRY_EPOCH=$(date -d "$NOT_AFTER" +%s 2>/dev/null || date -j -f "%b %d %T %Y %Z" "$NOT_AFTER" +%s 2>/dev/null || echo "0") NOW_EPOCH=$(date +%s) DAYS_REMAINING=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 )) # Determine status if [[ "$DAYS_REMAINING" -le 0 ]]; then STATUS="expired" elif [[ "$DAYS_REMAINING" -le 7 ]]; then STATUS="critical" elif [[ "$DAYS_REMAINING" -le 30 ]]; then STATUS="warning" else STATUS="valid" fi ``` ### Technical Analysis The connection invokes `openssl s_client` but does not require successful trust-chain validation or verify that the certificate identity matches the requested domain. The final status is determined exclusively from the certificate's expiration date. As a result, any parseable certificate with more than 30 days remaining can be labeled `valid`, including: - A self-signed certificate. - A certificate issued by an untrusted auth ...[truncated 1556 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • 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
Findings (7)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The code is partially aligned with the declared purpose because it does check website availability, HTTP status, redirects, and response timing, which fit site health and uptime-style checks. However, the declared description promises broader monitoring capabilities that are not implemented in this chunk: there is no SSL certificate expiry validation, no comparison of page content over time, no health report generation, and no alerting mechanism. The code is best described as a one-time website health probe rather than a full monitoring/alerting system. Therefore this is a description-behavior mismatch due to significant missing declared capabilities.

Content

No source excerpt is available for this finding.

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

Scanner excerpt · scripts/check_site.sh (reported line 30)May include surrounding context.

sh
exit 0
}

# Extract timing values from curl JSON output
STATUS_CODE=$(echo "$HTTP_CODE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('http_code',0))" 2>/dev/null || echo "0")
TIME_DNS=$(echo "$HTTP_CODE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(round(d.get('time_namelookup',0)*1000))" 2>/dev/null || echo "0")
TIME_CONNECT=$(echo "$HTTP_CODE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(round(d.get('time_connect',0)*1000))" 2>/dev/null || echo "0")

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
94% confidence
Finding

The skill invokes shell scripts (scripts/check_site.sh and scripts/check_ssl.sh) but does not declare any explicit tool scope or allowed-tools boundary. This weakens governance and reviewability because the skill appears harmless at the metadata layer while still requiring command execution, increasing the chance of unintended or overly broad shell access.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest description lists broad activation phrases such as "check website," "website health," "site status," and "check if a site is up" without any exclusion conditions or scope limits. These phrases are common enough that the skill could be invoked for general discussion or lightweight questions rather than intentional monitoring tasks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill directs the agent to create and update configuration and history files in the user's home/workspace without clearly surfacing that local writes will occur. Silent persistence can surprise users, create privacy concerns, and leave behind monitoring data or state that affects later runs.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
92% confidence
Finding

The script accepts a user-supplied URL and performs a server-side curl request to it, following redirects. In an agent context this creates an SSRF capability that can be abused to probe internal services, cloud metadata endpoints, or otherwise cause unintended outbound network access from the host running the skill.

Content

Scanner excerpt · scripts/check_site.sh (reported line 20)May include surrounding context.

sh
trap 'rm -f "$HEADER_FILE"' EXIT

# Perform the request with timing
HTTP_CODE=$(curl -s -o /dev/null -w '%{json}' \
  --max-time 15 \
  --connect-timeout 10 \
  -D "$HEADER_FILE" \

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
86% confidence
Finding

The skill instructs outbound HTTP/TLS checks against user-supplied targets without a user-facing notice that network requests will be made. While network access is core to this skill's purpose, lack of transparency can expose sensitive internal hostnames or trigger scans against unintended systems if the user is not clearly informed.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.