Back to skill

Security audit

Skill 4

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but its unrestricted URL fetching can be used to probe private/internal services from the user's environment.

Review before installing in environments with access to private networks, cloud metadata services, or sensitive internal web apps. Use it only for trusted, intended URLs, preferably with network egress controls that block localhost/private ranges and with response-size limits if adapted for production monitoring.

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

T09 · Insecure Skill Coding Practices

Warning
Location
main.py:23
Finding
Unrestricted URL Fetching Enables SSRF-Style Internal Network Probing## Vulnerability Details **File Location**: `main.py`, lines 23-28 and 100-104 **Vulnerability Type**: Server-Side Request Forgery (SSRF) / unrestricted outbound requests **Risk Level**: Medium ### Vulnerable Code ```python headers = {'User-Agent': 'website-monitor/1.0 (ClawHub)'} req = Request(url, headers=headers) start = time.monotonic() try: resp = urlopen(req, timeout=timeout) ``` The attacker-controlled URL reaches this request through: ```python results = [] for url in args.urls: if not url.startswith(('http://', 'https://')): url = 'https://' + url r = check_url(url, args.timeout, args.expect, args.contains, args.hash_check) ``` ### Technical Analysis The application makes network requests to user-supplied URLs without validating the destination hostname, resolved IP address, port, or redirect target. It does not prevent connections to loopback, private, link-local, reserved, or cloud metadata address ranges. Python's `urlopen` also follows supported HTTP redirects by default. Consequently, validating only the initial URL scheme would not be sufficient: a public URL could redirect the request to an internal resource unless every redirect destination is independently validated. Although the response body is not printed directly, the program exposes several response oracles: - HTTP status - Response time - Response length - Truncated SHA-256 content hash - Whether attacker-selected text occurs in the response These values can be used to discover internal services and infer information about resources that are accessible from the host running the skill. ### Attack Path 1. An attacker causes an AI agent or automation workflow to invoke the skill with an attacker-selected URL. 2. The URL directly references an internal endpoint, such as a loopback, private-network, or link-local address, or references a public endpoint that redirects to one. 3. `urlopen` connect ...[truncated 932 chars]
Remediation
## Remediation Suggestions 1. Parse URLs with `urllib.parse.urlsplit` and permit only explicitly supported schemes, preferably HTTPS. 2. Reject embedded credentials, malformed hostnames, unexpected ports, and ambiguous numeric IP representations. 3. Resolve the hostname before connecting and reject every address in loopback, private, link-local, multicast, unspecified, reserved, and other non-public ranges using Python's `ipaddress` module. 4. Protect against DNS rebinding by ensuring that the validated address is the address used for the connection, or by applying equivalent network-layer egress controls. 5. Disable automatic redirects or validate the scheme, hostname, port, and resolved addresses of every redirect target before following it. 6. Restrict outbound ports and apply a destination allowlist when the set of monitored websites is known. 7. Run the skill in a sandbox with network egress rules that block internal and metadata networks. 8. If internal monitoring is a required feature, make it an explicit trusted-mode option rather than the default.

T09 · Insecure Skill Coding Practices

Note
Location
main.py:28
Finding
Unbounded Response Buffering Can Cause Resource Exhaustion## Vulnerability Details **File Location**: `main.py`, line 28 **Vulnerability Type**: Uncontrolled resource consumption **Risk Level**: Low ### Vulnerable Code ```python resp = urlopen(req, timeout=timeout) elapsed = (time.monotonic() - start) * 1000 body = resp.read() ``` ### Technical Analysis Calling `resp.read()` without a size argument reads the entire response body into memory. No maximum body size is enforced, and the response is buffered before hashing or text verification occurs. The connection timeout limits some network operations but does not establish a total response-size limit. A malicious or misconfigured server can therefore return a very large body or sustain a response long enough to consume excessive memory and execution time. Checking multiple attacker-controlled URLs can amplify the effect because every response is processed sequentially in the same process. ### Attack Path 1. An attacker supplies a URL under their control or compromises a monitored endpoint. 2. The endpoint returns an extremely large response body or a long-running data stream. 3. The application executes `resp.read()` and attempts to buffer the complete response in memory. 4. Memory consumption and processing time increase until the request completes, the process is terminated, or the host experiences resource pressure. 5. Repeated invocations or multiple supplied URLs can cause recurring denial of service. ### Impact Assessment This issue does not provide additional privileges or direct access to sensitive data. Its primary impact is availability: the monitor process can become unresponsive, be terminated by the operating system, or contribute to memory exhaustion affecting other workloads on the same host or container. The practical scope depends on process memory limits, host isolation, response size, and how frequently untrusted URLs can trigger the skill.
Remediation
## Remediation Suggestions 1. Define a strict maximum response size appropriate for uptime monitoring. 2. Read the response incrementally in bounded chunks instead of calling `resp.read()` without a limit. 3. Update the SHA-256 digest incrementally while streaming. 4. Abort the request and return a clear error as soon as the cumulative byte count exceeds the configured limit. 5. For text matching, use a bounded streaming search that retains only enough overlap to detect matches spanning chunk boundaries. 6. Consider rejecting responses whose declared `Content-Length` exceeds the limit, while still enforcing the streaming limit because that header may be missing or dishonest. 7. Apply process or container memory limits and a total request deadline as defense-in-depth controls.
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (2)

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill performs network operations against arbitrary user-supplied URLs, but the manifest does not explicitly declare any tool scope or permissions. This creates a governance and least-privilege gap: the skill can make outbound requests without clear permission boundaries, increasing the risk of unintended network access, misuse for probing internal resources, or deployment in environments that rely on manifest-declared capabilities.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The trigger phrases are generic and likely to match common user requests such as 'is site up' or 'check website', which can cause the skill to activate unexpectedly. In a network-capable skill, accidental activation is more dangerous because it may initiate outbound requests to attacker-influenced URLs or expose the agent to prompt-routing abuse and unreviewed network actions.

Static analysis

No suspicious patterns detected.