Back to skill

Security audit

Service Watchdog

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real service monitor, but unsafe configuration handling could let a bad config run commands or damage writable files.

Install only after fixing or accepting these risks. Use this only with trusted watchdog.json files, avoid untrusted host, port, URL, and history_file values, prefer disabling history or confining it to a dedicated directory, and do not rely on HTTPS results for certificate trust until the insecure TLS behavior is corrected.

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
watchdog.sh:238
Finding

Shell Command Injection Through the TCP Check Fallback

Content
View full analysis
/dev/tcp/${host}/${port}" 2>/dev/null; then success=true fi fi ``` The values reaching the vulnerable operation are read from the configuration without validation: ```bash host=$(echo "$svc" | jq -r '.host') port=$(echo "$svc" | jq -r '.port') timeout_ms=$(echo "$svc" | jq -r ".timeout_ms // $DEFAULT_TIMEOUT_MS") result=$(check_tcp "$host" "$port" "$timeout_ms") ``` ### Technical Analysis The `host` and `port` values originate in `watchdog.json`. When neither `nc` nor `ncat` is installed, they are interpolated directly into a command string passed to `bash -c`. Quoting the overall argument to `bash -c` does not make the interpolated content safe. Shell metacharacters contained in either value become part of the command text parsed by the newly launched shell. An attacker capable of modifying or supplying the watchdog configuration can therefore introduce command substitutions, command separators, redirections, or pipelines. For example, a malicious host value containing shell syntax could cause an additional command to run when the fallback is reached. Exploitation depends on the absence of both `nc` and `ncat`, but the fallback is explicitly supported and documented by the Skill. ### Attack Path 1. An attacker gains the ability to create or modify the JSON configuration used by the Skill, including through a user-provided `--config` path or `WATCHDOG_CONFIG`. 2. The attacker defines a TCP service and inserts shell metacharacters into its `host` or `port` field. 3. The user or Agent invokes `watchdog.sh` as documented. 4. The target environment does not have `nc` or `ncat`, causing execution to enter the `/dev/tcp` fallback. 5. The untrusted values are interpolated into the string passed to ...[truncated 718 chars]
Remediation
View remediation
= 1 && port <= 65535 )) || { echo "fail|0|Invalid TCP port" return } [[ "$host" =~ ^[A-Za-z0-9._:-]+$ ]] || { echo "fail|0|Invalid TCP host" return } if timeout "$timeout_s" bash -c \ 'exec 3<>"/dev/tcp/$1/$2"' bash "$host" "$port" 2>/dev/null; then success=true fi ``` The hostname validation should be made more precise if internationalized names or IPv6 zone identifiers must be supported. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
watchdog.sh:119
Finding

Unrestricted History Path Allows Arbitrary Writable-File Corruption or Replacement

Content
View full analysis
"$HISTORY_FILE" fi } write_history() { if [[ "$WRITE_HISTORY" == "true" ]]; then local name="$1" type="$2" status="$3" response_ms="$4" detail="$5" # CSV-escape fields with commas/quotes detail="${detail//\"/\"\"}" echo "${NOW_UTC},\"${name}\",${type},${status},${response_ms},\"${detail}\"" >> "$HISTORY_FILE" fi } prune_history() { if [[ "$WRITE_HISTORY" == "true" ]] && [[ -f "$HISTORY_FILE" ]]; then local cutoff_epoch=$((NOW_EPOCH - DEFAULT_HISTORY_RETENTION_DAYS * 86400)) local cutoff_date cutoff_date=$(date -u -d "@${cutoff_epoch}" '+%Y-%m-%d' 2>/dev/null || date -u -r "${cutoff_epoch}" '+%Y-%m-%d' 2>/dev/null || echo "") if [[ -n "$cutoff_date" ]]; then local tmp="${HISTORY_FILE}.tmp" head -1 "$HISTORY_FILE" > "$tmp" awk -F',' -v cutoff="$cutoff_date" 'NR>1 && $1 >= cutoff' "$HISTORY_FILE" >> "$tmp" mv "$tmp" "$HISTORY_FILE" fi fi } ``` ### Technical Analysis The `defaults.history_file` property can point outside the workspace, including to an absolute path. The script neither canonicalizes the path nor verifies that it remains within a dedicated history directory. Several unsafe operations follow: - `init_history` creates a configured path if it does not already exist. - `write_history` appends atta ...[truncated 2024 chars]
Remediation
View remediation
&2 exit 1 } tmp=$(mktemp "$HISTORY_DIR/.history.XXXXXX") trap 'rm -f -- "$tmp"' EXIT ``` The final implementation should also reject special files and ensure that the canonical history directory is not itself a symlink-controlled location. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
watchdog.sh:178
Finding

HTTPS Monitoring Disables Certificate Authentication

Content
View full analysis
/dev/null | \ openssl x509 -noout -enddate 2>/dev/null | sed 's/notAfter=//') ``` ```bash cert_info=$(echo | openssl s_client -servername "$host" -connect "${host}:${port}" 2>/dev/null | \ openssl x509 -noout -enddate -issuer -subject 2>/dev/null) ``` ### Technical Analysis The HTTP check always supplies `--insecure` to `curl`. For HTTPS URLs, this disables normal certificate-chain and hostname verification. The monitor will therefore accept self-signed certificates, certificates issued by an untrusted authority, and certificates issued for a different hostname. The separate OpenSSL logic does not compensate for this weakness. It extracts the presented certificate's expiry, issuer, and subject, but does not verify that the chain terminates in a trusted root or that the certificate identity matches the requested host. A forged certificate with a plausible validity period can consequently be reported as healthy. This contradicts the security purpose of HTTPS monitoring because endpoint reachability and certificate lifetime are checked without authenticating the endpoint's identity. ### Attack Path 1. An attacker obtains a network interception position or influences DNS or routing for a monitored HTTPS endpoint. 2. The attacker redirects the watchdog connection to an attacker-controlled TLS server. 3. The server presents any currently valid-looking certificate, including a self-s ...[truncated 1015 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (3)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The skill explicitly instructs the agent to run active network checks, including cron-based repeated execution, but does not warn that this will initiate connections to configured internal or external hosts and may record sensitive infrastructure details such as hostnames, IPs, ports, and certificate metadata in outputs or logs. In an agent setting, that omission can cause operators to trigger scanning-like behavior or disclose internal topology without realizing the privacy and security implications.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The help text presents '--ssl-only' as a mode to check SSL certificates only, implying certificate-focused validation. However, the main HTTP check path uses curl with '--insecure' at L160-L162, so normal HTTPS monitoring explicitly skips TLS certificate verification even though the skill is framed as endpoint/SSL monitoring. This is an intent-level contradiction between the documented monitoring purpose and the code's actual trust behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script invokes curl with --insecure for all HTTP/HTTPS checks, which disables TLS certificate validation and allows a man-in-the-middle attacker to spoof an HTTPS endpoint while still producing a successful health check. In a monitoring skill, this is especially dangerous because it can hide certificate misconfiguration, interception, or endpoint impersonation and give operators false assurance that a service is healthy.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.