Back to skill

Security audit

Local Places

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it claims, but its included server can expose an unauthenticated Google Places API-key proxy beyond localhost, creating billing, quota, and location-privacy risk.

Review before installing or running. Use only loopback binding, avoid the SERVER_README.md 0.0.0.0 command unless you add authentication and network controls, restrict the Google API key in Google Cloud, do not set GOOGLE_PLACES_BASE_URL to untrusted hosts, and avoid submitting sensitive home, work, or routine locations unless you accept that they may be sent to Google and written to logs on validation errors.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (3)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
SERVER_README.md:10
Finding

Unauthenticated API-key-backed proxy exposed on all network interfaces

Content
View full analysis
SearchResponse: return search_places(request) @app.get("/places/{place_id}", response_model=PlaceDetails) def places_details(place_id: str) -> PlaceDetails: return get_place_details(place_id) @app.post("/locations/resolve", response_model=LocationResolveResponse) def locations_resolve(request: LocationResolveRequest) -> LocationResolveResponse: return resolve_locations(request) ``` ```python # src/local_places/main.py:62-65 if __name__ == "__main__": import uvicorn uvicorn.run("local_places.main:app", host="0.0.0.0", port=8000) ``` ### Technical Analysis The application exposes all Google Places proxy operations without authentication, authorization, or rate limiting. Both the documented startup command and the direct Python entry point bind the service to `0.0.0.0`, making it available through every network interface permitted by the host firewall. Each request is subsequently authenticated to Google using the server owner's `GOOGLE_PLACES_API_KEY`. Consequently, any network client that can reach port 8000 can indirectly exercise the authority and quota associated with that credential. This exceeds the minimum privileges necessary for the declared localhost-only Skill functionality in `SKILL.md`, which instructs clients to use `127.0.0.1`. The documented use of Uvicorn's `--reload` option also unnecessari ...[truncated 1337 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/local_places/google_places.py:17
Finding

Google Places API key can be transmitted to an arbitrary configured destination

Content
View full analysis
dict[str, str]: api_key = os.getenv("GOOGLE_PLACES_API_KEY") if not api_key: raise HTTPException( status_code=500, detail="GOOGLE_PLACES_API_KEY is not set.", ) return { "Content-Type": "application/json", "X-Goog-Api-Key": api_key, "X-Goog-FieldMask": field_mask, } def _request( method: str, url: str, payload: dict[str, Any] | None, field_mask: str ) -> _GoogleResponse: try: with httpx.Client(timeout=10.0) as client: response = client.request( method=method, url=url, headers=_api_headers(field_mask), json=payload, ) except httpx.HTTPError as exc: raise HTTPException(status_code=502, detail="Google Places API unavailable.") from exc return _GoogleResponse(response) ``` ### Technical Analysis The API destination is accepted directly from the `GOOGLE_PLACES_BASE_URL` environment variable without validating its scheme or hostname. The `_request` function then unconditionally adds the production Google API key to requests sent to that destination. The default value is the legitimate HTTPS Google Places endpoint, and no attacker-controlled endpoint is hard-coded. Nevertheless, configuration mistakes or influence over process environment variables can cause the key to be transmitted to an arbitrary HTTP or HTTPS server. An HTTP override would additionally expose the credential in plaintext to network observers. An ...[truncated 1555 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/local_places/main.py:25
Finding

Validation failures log complete user-supplied request bodies

Content
View full analysis
JSONResponse: logger.error( "Validation error on %s %s. body=%s errors=%s", request.method, request.url.path, exc.body, exc.errors(), ) ``` ### Technical Analysis The validation exception handler writes `exc.body`, containing the complete parsed request body, to error logs whenever Pydantic validation fails. Requests can contain precise coordinates, location descriptions, search preferences, page tokens, or accidentally supplied credentials and personal information. Logging the full body is not necessary to diagnose which schema fields failed validation. Error-level records are also commonly forwarded to centralized log systems and retained longer than ordinary application data, expanding the number of systems and personnel able to access the information. Because validation errors can be intentionally triggered, an external client can cause arbitrary attacker-selected request content to be persisted in logs. This may also facilitate log-volume amplification, although newline rendering and downstream logger behavior determine whether log-forging is practical. ### Attack Path 1. A client prepares a request containing sensitive information in valid fields, unknown fields, or otherwise malformed content. 2. The client intentionally violates a schema rule, such as supplying an out-of-range coordinate or invalid `limit`. 3. FastAPI raises `RequestValidationError`. 4. The custom exception handler reads `exc.body`. 5. The entire request body is written at error level. 6. The data persists in local files, process output, container logs, or a cen ...[truncated 782 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (5)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill explicitly requires an environment variable API key and instructs the user to run a local HTTP service, which implies both environment and network capabilities, yet it declares no permissions. This undermines transparency and informed consent because users and reviewers may believe the skill is lower-privilege than it really is.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

The skill is presented as using a localhost proxy for local place search, but the documented and detected behavior includes resolving free-text locations, fetching place details, and potentially connecting directly to Google Places APIs. This description-behavior mismatch is dangerous because it can mislead users about data flows and trust boundaries, especially where sensitive location queries are involved.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README states that user-provided place queries and location strings are sent to the Google Maps Places API, but it does not clearly warn that this data leaves the local system and is transmitted to a third party. In an agent setting, users may provide sensitive addresses, routines, or points of interest, so the missing disclosure can lead to privacy violations and unintentionally unsafe handling of location data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill encourages users to submit location text and place searches without warning that this information may be transmitted to a local proxy and potentially onward to Google Places services. Because location and search intent can be sensitive, omission of this disclosure creates a privacy risk and prevents meaningful user consent.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: uvicorn — 4 advisory(ies): CVE-2020-7694 (Log injection in uvicorn); CVE-2020-7695 (HTTP response splitting in uvicorn); CVE-2020-7694 (This affects all versions of package uvicorn. The request logger provided by the) +1 more

High
Category
Supply Chain
Confidence
74% confidence
Finding

uvicorn[standard]>=0.29.0 allows any future version at or above 0.29.0, but the cited Uvicorn advisories historically affected older releases and may or may not be fixed depending on resolved version. In a localhost API proxy skill, Uvicorn is directly internet-facing in development or local network contexts, so logging or response-splitting flaws could matter if an affected version is installed.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.