Back to skill

Security audit

Location Service

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its location-service purpose, but it needs review because its automatic link resolver can make unsafe outbound requests and its dispatcher runs helper scripts from a fixed external path.

Review before installing in any environment with access to internal services or sensitive network metadata. Avoid submitting home, workplace, or current-location details unless you are comfortable sending them to external geocoding providers, and prefer a version that validates exact URL hostnames, restricts redirects, and runs bundled helper scripts by relative path.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/location_service.py:45
Finding
Server-Side Request Forgery Through Incomplete Host Validation and Unrestricted Redirects<![CDATA[ ## Vulnerability Details **File Location**: `scripts/location_service.py`, lines 45–58 **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: High ### Vulnerable Code ```python def is_google_maps_url(text): """Check if text looks like a Google Maps URL (standard or short)""" return bool(re.match( r'https?://(maps\.google\.com|www\.google\.com/maps|maps\.app\.goo\.gl)', text.strip() )) def resolve_short_url(url): """Follow redirects on a short URL and return the final URL""" try: req = urllib.request.Request(url, headers={'User-Agent': 'LocationService/1.0'}) with urllib.request.urlopen(req, timeout=10) as resp: return resp.url except Exception as e: raise ValueError(f"Failed to resolve short URL: {e}") ``` The short-link resolution path is invoked by the following logic at lines 73–75: ```python # Resolve short URLs first if 'maps.app.goo.gl' in url: url = resolve_short_url(url) ``` ### Technical Analysis The URL validation uses a regular expression that does not enforce a boundary after the expected hostname. For example, an attacker-controlled URL with a hostname such as: ```text https://maps.app.goo.gl.attacker.example/path ``` matches the `maps.app.goo.gl` prefix and is accepted as a Google Maps URL. The subsequent substring check also treats this URL as a short Google Maps link and passes it to `urllib.request.urlopen`. That API follows HTTP redirects by default. Neither the initial destination nor any redirect destination is validated using parsed hostname equality, DNS resolution checks, or private-address filtering. Consequently, an attacker-controlled endpoint can redirect the request to loopback, link-local, private-network, or cloud metadata addresses. Although the response body is not directly returned, issuing the GET request can still access state-changing internal endpoints and provide a blind SSRF channel through status, timing ...[truncated 1792 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse input with `urllib.parse.urlsplit` instead of validating URLs with a prefix regular expression. 2. Require `https` and exact, case-normalized hostname equality: ```python from urllib.parse import urlsplit def is_google_maps_short_url(value): parsed = urlsplit(value.strip()) return ( parsed.scheme == "https" and parsed.hostname is not None and parsed.hostname.lower() == "maps.app.goo.gl" and parsed.username is None and parsed.password is None ) ``` 3. Disable automatic redirects and process each redirect manually. 4. On every redirect, repeat scheme and hostname validation rather than trusting the initial destination. 5. Resolve destination hostnames and reject all loopback, private, link-local, multicast, unspecified, reserved, and otherwise non-public IPv4 and IPv6 addresses. 6. Defend against DNS rebinding by validating resolved addresses immediately before connecting and ensuring the connection uses the validated address. 7. Set strict redirect-count, response-size, and timeout limits. 8. Consider removing server-side short-link resolution entirely if it is not essential. ]]>

T07 · Tool Hijacking and Spoofing

Warning
Location
scripts/location_service.py:105
Finding
Execution of Python Scripts From an External Hard-Coded Workspace Path<![CDATA[ ## Vulnerability Details **File Location**: `scripts/location_service.py`, lines 13–29, 105–107, 164–165, 182–183, and 193–194 **Vulnerability Type**: External Tool Hijacking and Local Code Substitution **Risk Level**: Medium ### Vulnerable Code The helper executes the supplied script path using the current Python interpreter: ```python def run_script(script_path, args): """Run a Python script and return its output""" try: result = subprocess.run( [sys.executable, script_path] + args, capture_output=True, text=True, timeout=30 ) if result.returncode == 0: return result.stdout.strip(), None else: return None, result.stderr.strip() except subprocess.TimeoutExpired: return None, "Error: Script execution timed out" except Exception as e: return None, f"Error: {str(e)}" ``` Call sites use absolute paths outside the audited project artifact: ```python script_path = "/home/ubuntu/.openclaw/workspace/skills/location-service/scripts/geocode_forward.py" out, err = run_script(script_path, [location_spec]) ``` ```python script_path = "/home/ubuntu/.openclaw/workspace/skills/location-service/scripts/distance_calc.py" distance_out, distance_err = run_script(script_path, [str(lat1), str(lon1), str(lat2), str(lon2)]) ``` ```python script_path = "/home/ubuntu/.openclaw/workspace/skills/location-service/scripts/geocode_reverse.py" address_out, address_err = run_script(script_path, [str(lat), str(lon)]) ``` ```python script_path = "/home/ubuntu/.openclaw/workspace/skills/location-service/scripts/geocode_forward.py" coords_out, coords_err = run_script(script_path, [input_text]) ``` ### Technical Analysis The dispatcher does not derive subordinate script paths from the installed `location_service.py` file or otherwise ensure that it executes the scripts contained in the audited package. Instead, it invokes Python files from a fix ...[truncated 2079 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Resolve subordinate scripts relative to the currently executing package rather than through an external hard-coded workspace path: ```python from pathlib import Path SCRIPT_DIR = Path(__file__).resolve().parent forward_script = SCRIPT_DIR / "geocode_forward.py" reverse_script = SCRIPT_DIR / "geocode_reverse.py" distance_script = SCRIPT_DIR / "distance_calc.py" ``` Before execution: 1. Require the resolved path to remain inside `SCRIPT_DIR`. 2. Reject symbolic links if deployment policy does not require them. 3. Ensure the installed skill directory and script files are not writable by less-trusted users, processes, or skills. 4. Package and deploy the dispatcher and subordinate scripts as one immutable or integrity-protected unit. 5. Where appropriate, verify script hashes or signatures before execution. 6. Prefer importing trusted sibling modules and calling their functions directly instead of spawning separate Python interpreters. 7. Run the skill with the minimum required filesystem and network privileges so that any future code-substitution issue has limited impact. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (9)

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill advertises behavior that depends on network access and executable scripts, but it does not declare any tool scope or permissions boundaries. This weakens reviewability and can cause the skill to run with broader capabilities than users or the platform expect, increasing the risk of unintended network access or shell execution.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The skill states that it sends addresses, coordinates, and weather queries to external services such as Nominatim and weather integrations, but it does not present an explicit privacy warning to users. Location data is often sensitive, and silent transmission to third parties can expose home, work, or travel information.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The Google Maps short-link feature implicitly performs an HTTP request to resolve third-party URLs, but the skill does not warn users before doing so. A pasted link may therefore trigger outbound requests and disclose metadata or user intent to external services without informed consent.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
This documentation describes sending addresses and coordinates to the public Nominatim service but does not warn users that potentially sensitive location data is transmitted to an external third party. In a location-service skill, that omission matters because geocoding inputs can reveal home, work, travel, or other private user information, creating privacy and compliance risk even if the API usage itself is legitimate.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script sends user-supplied address data to the external Nominatim geocoding service, which can expose potentially sensitive location information to a third party without any notice, consent flow, or privacy control. In a location-service skill, this behavior is functionally expected, but it still creates a real privacy risk because users may submit home, work, or other sensitive addresses assuming local processing.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The script sends precise user-supplied latitude and longitude to the external Nominatim service, which can expose sensitive location data to a third party without any disclosure, consent flow, or privacy notice. Exact coordinates may reveal a user's home, workplace, or current whereabouts, so the issue is a real privacy/security concern even though the network call is functionally required for reverse geocoding.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def run_script(script_path, args):
    """Run a Python script and return its output"""
    try:
        result = subprocess.run(
            [sys.executable, script_path] + args,
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
Resolving a maps.app.goo.gl URL causes an outbound network request to Google using user-supplied input, which can disclose that the user is processing a specific location link and may expose metadata such as IP address and access timing. In an agent skill context, this is more sensitive because users may not realize that simply parsing a URL triggers external contact.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The skill geocodes addresses and reverse-geocodes coordinates via helper scripts without any explicit notice that precise location data may be transmitted to external geocoding services. Location information is sensitive personal data, and in this skill’s context that makes undisclosed data egress more dangerous than in a generic text-processing tool.

Static analysis

No suspicious patterns detected.