Back to skill

Security audit

Web Browsing

Security checks for vulnerabilities and agentic risk

Overview

This web-browsing skill does what it says, but needs review because it can fetch any URL from the agent's network without safeguards.

Install only if you are comfortable with the agent sending your search terms and provided URLs to external services. Do not use it with secrets, private/internal URLs, credentials in query strings, or sensitive personal data unless the runtime has strong outbound network controls. The publisher should add URL validation, redirect revalidation, private-network blocking, download limits, and clear privacy disclosure before this is treated as low-risk.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/search_web.py:63
Finding
Server-Side Request Forgery Through Unrestricted URL Fetching<![CDATA[ ## Vulnerability Details **File Location**: `scripts/search_web.py`, lines 63-83 **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High ### Vulnerable Code ```python def fetch_url(url: str) -> dict: """ Fetch and parse a webpage. Args: url: URL to fetch Returns: Dictionary with title, content, and metadata """ headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' } try: response = requests.get(url, headers=headers, timeout=15, allow_redirects=True) response.raise_for_status() soup = BeautifulSoup(response.text, 'html.parser') ``` ### Technical Analysis The `fetch_url` function passes a caller-controlled URL directly to `requests.get()` without validating its scheme, hostname, resolved IP address, port, or destination network. Consequently, an attacker who can supply a URL can cause the process to issue HTTP requests to resources reachable from the host running this skill, including: - Loopback services such as `127.0.0.1` or `[::1]`. - Private-network services in RFC 1918 address ranges. - Link-local addresses and potential cloud instance metadata services. - Internal services that are not externally reachable. - Redirect destinations, because `allow_redirects=True` is enabled without revalidating each redirect target. - Hostnames that resolve to prohibited addresses or use DNS rebinding to change their resolution between validation and connection. The response body is extracted and returned in the `content` field, up to 5,000 characters. This makes the issue a response-disclosing SSRF rather than merely a blind SSRF. Although the returned content is truncated, `requests` downloads the response before truncation, so a malicious or unexpectedly large response may also consume excessive memory. ### Attack Path 1. An attacker asks the agent or another caller to fetch an attacker-select ...[truncated 1655 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Restrict accepted schemes to `https`, or to `http` and `https` only when plaintext HTTP is explicitly required. 2. Use an allowlist of approved domains where the use case permits it. A denylist alone is insufficient. 3. Resolve the hostname before connecting and reject every resolved IPv4 and IPv6 address that is loopback, private, link-local, multicast, reserved, unspecified, or otherwise non-global. 4. Disable automatic redirects with `allow_redirects=False`, or inspect and revalidate the scheme, hostname, port, and resolved addresses of every redirect target before following it. 5. Protect against DNS rebinding by ensuring the validated address is the address actually used for the connection. Consider routing requests through a hardened outbound proxy that enforces destination policy. 6. Block cloud metadata addresses and platform-specific internal service ranges at both the application and network layers. 7. Enforce an explicit port policy, preferably limiting requests to ports 80 and 443 unless other ports are required. 8. Use streamed responses and enforce a maximum download size before loading response content into memory. 9. Apply outbound firewall or container-network rules so the skill cannot reach loopback-adjacent services, private networks, metadata endpoints, or other sensitive destinations. 10. Add automated tests covering IPv4, IPv6, alternate address representations, redirect chains, hostname resolution to private addresses, and DNS-rebinding scenarios. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (4)

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill clearly enables network-capable actions such as web search and URL fetching, but it does not declare an explicit tool scope or permission boundary. This creates a governance and least-privilege issue because consumers and enforcement layers cannot easily verify or constrain what network actions the skill is expected to perform.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill invites users to provide search terms and URLs but does not disclose that those inputs will be transmitted to external search engines or target websites. This is dangerous because users may unknowingly submit sensitive queries, internal URLs, tokens in query strings, or other private information to third parties.

Missing User Warnings

Medium
Confidence
86% confidence
Finding
This code sends the user's search query to DuckDuckGo via an HTTP request, which is a privacy-relevant network operation. Although the docstring describes functionality, there is no user-facing warning, confirmation, or runtime disclosure that the query will be transmitted to an external service.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
`fetch_url` performs arbitrary outbound requests to attacker-controlled or user-supplied URLs with redirects enabled and no validation of scheme, host, or destination class. In an agent environment, this can be abused for SSRF-style access to internal services, cloud metadata endpoints, or other network resources reachable from the runtime, making the browsing context materially more dangerous than a normal standalone browser fetcher.

Static analysis

No suspicious patterns detected.