T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/amap_ip_location.py:35- Finding
Automatic multi-party public IP discovery with VPN-bypass intent
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This POI planner is mostly purpose-aligned, but it automatically uses privacy-sensitive location discovery and an unverified sibling search script in ways users should review carefully.
Install only if you are comfortable sending addresses, coordinates, search terms, and possibly your public IP to Amap, OSM/Overpass, Maoyan, IP lookup providers, and the sibling unified-search providers. Keep .env.local limited to the Amap key, verify the sibling unified-search skill yourself, and avoid using automatic nearby/current-location mode if IP privacy matters.
scripts/amap_ip_location.py:35Automatic multi-party public IP discovery with VPN-bypass intent
scripts/providers.py:11Overbroad secret-file ingestion exposes unrelated environment variables to subprocesses
scripts/planner.py:448Unpinned executable sibling-Skill dependency creates a local supply-chain execution boundary
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
req = urllib.request.Request(full_url, method="GET")
req.add_header("Accept", "application/json")
ctx = ssl.create_default_context()
with urllib.request.urlopen(req, timeout=timeout, context=ctx) as resp:
return json.loads(resp.read().decode("utf-8", errors="replace"))
except Exception as e:
return {"error": str(e)}
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
url = f"{GEOCODE_API_URL}?{query_string}"
req = urllib.request.Request(url, headers={"Accept": "application/json"})
with urllib.request.urlopen(req, timeout=10) as response:
data = json.loads(response.read().decode("utf-8", errors="replace"))
if data.get("status") != "1":
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
try:
url = f"https://restapi.amap.com/v3/geocode/regeo?location={lon},{lat}&key={key}&radius=1000&extensions=base"
req = urllib.request.Request(url)
with urllib.request.urlopen(req, timeout=5) as resp:
data = json.loads(resp.read().decode("utf-8"))
if data.get("status") == "1":
comp = data["regeocode"]["addressComponent"]
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def _load_env_file():
"""Simple .env.local loader without external dependencies"""
try:
env_path = os.path.join(os.path.dirname(__file__), '..', '.env.local')
with open(env_path, 'r') as f:
for line in f:
line = line.strip()
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def _load_env_file():
"""Simple .env.local loader without external dependencies"""
try:
env_path = os.path.join(os.path.dirname(__file__), '..', '.env.local')
with open(env_path, 'r') as f:
for line in f:
line = line.strip()
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
import socket
from pathlib import Path
# Load .env.local if exists
SCRIPT_DIR = Path(__file__).parent.resolve()
ENV_FILE = SCRIPT_DIR.parent / ".env.local"
if ENV_FILE.exists():
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
import socket
from pathlib import Path
# Load .env.local if exists
SCRIPT_DIR = Path(__file__).parent.resolve()
ENV_FILE = SCRIPT_DIR.parent / ".env.local"
if ENV_FILE.exists():
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
import socket
from pathlib import Path
# Load .env.local if exists
SCRIPT_DIR = Path(__file__).parent.resolve()
ENV_FILE = SCRIPT_DIR.parent / ".env.local"
if ENV_FILE.exists():
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
import socket
from pathlib import Path
# Load .env.local if exists
SCRIPT_DIR = Path(__file__).parent.resolve()
ENV_FILE = SCRIPT_DIR.parent / ".env.local"
if ENV_FILE.exists():
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
import socket
from pathlib import Path
# Load .env.local if exists
SCRIPT_DIR = Path(__file__).parent.resolve()
ENV_FILE = SCRIPT_DIR.parent / ".env.local"
if ENV_FILE.exists():
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
import socket
from pathlib import Path
# Load .env.local if exists
SCRIPT_DIR = Path(__file__).parent.resolve()
ENV_FILE = SCRIPT_DIR.parent / ".env.local"
if ENV_FILE.exists():
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# Load .env.local if exists
SCRIPT_DIR = Path(__file__).parent.resolve()
ENV_FILE = SCRIPT_DIR.parent / ".env.local"
if ENV_FILE.exists():
with open(ENV_FILE, "r", encoding="utf-8") as f:
for line in f:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# Load .env.local if exists
SCRIPT_DIR = Path(__file__).parent.resolve()
ENV_FILE = SCRIPT_DIR.parent / ".env.local"
if ENV_FILE.exists():
with open(ENV_FILE, "r", encoding="utf-8") as f:
for line in f:
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
# Load .env.local if exists
SCRIPT_DIR = Path(__file__).parent.resolve()
ENV_FILE = SCRIPT_DIR.parent / ".env.local"
if ENV_FILE.exists():
with open(ENV_FILE, "r", encoding="utf-8") as f:
for line in f:
The document explicitly reveals where sensitive credentials are stored, including a search credentials file and an environment file containing an Amap API key. Even without disclosing the secret values themselves, publishing exact storage locations lowers the effort for an attacker or a malicious downstream tool to target and exfiltrate those files, especially in an agentic environment that may read local paths automatically.
The document is written entirely in Chinese and includes no indication that language choice is optional or limited to a justified region-specific context. Under the policy, forcing a specific language without user opt-in is a natural-language locale violation.
The template hard-codes Chinese section headers and expected output structure without any indication that language should be chosen based on user preference or locale. This can cause the agent to ignore user language expectations, leading to misleading, inaccessible, or unusable responses, especially in multilingual environments.
Output size or generation rate is not bounded. Unbounded output enables denial-of-service through resource exhaustion, log flooding, or context-window stuffing.
def format_transit_detail_lines(details: Optional[Dict], max_parts: int = 0) -> list[str]:
"""Render concise, user-facing transit detail lines.
max_parts <= 0 means no truncation (render the full route).
"""
if not details:
return []
The skill generates natural-language output strings entirely in Chinese, such as route summaries and step instructions, with no opt-in or alternative locale support. That creates a language-policy concern because the skill effectively forces a specific language for user-facing output without documenting the restriction or letting the user choose.
This Python code sends user-provided addresses and origin/destination coordinates to the external Amap API via HTTP requests, which can reveal sensitive location data. While the module docstrings describe functionality, the operational functions do not provide any user-facing warning, confirmation, or explicit disclosure that location data is transmitted to a third-party service.
The module docstring states that it supports parsing arbitrary Chinese addresses, which imposes a language/locale expectation in natural language. Because the file does not offer an opt-in choice or explain that the skill is intentionally region-specific, this can violate the language/locale policy for skills that should not force a specific locale implicitly.
The code sends requests to several third-party IP lookup services and then to Amap, disclosing the user's public IP and enabling correlation of network metadata across multiple providers. The explicit goal of finding a 'real (non-VPN) public IP' and preferring a provider that may bypass VPN protections makes this materially more privacy-invasive than ordinary geolocation.
The module-level documentation says the provider uses typecode-based precise search to replace fuzzy keyword search. However, in the main search flow, when a keyword is supplied, the code explicitly avoids passing any typecode and calls _search_with_typecode(..., None, keywords=keyword), making the actual behavior keyword-only rather than typecode-constrained.
This Python skill contains user-facing natural language in the module docstring and later console output exclusively in Chinese, which effectively imposes a specific language/locale. The policy requires flagging forced language usage when the skill does not offer an explicit language choice or justify the locale restriction.
The function transmits user location coordinates and search keywords to the external Amap API, which can reveal sensitive behavioral and geolocation data to a third party. In a skill context, lack of explicit disclosure or consent increases privacy risk because users may not realize their precise location and interests are being sent off-platform.
No suspicious patterns detected.