Back to skill

Security audit

Amap Navigation

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real AMap navigation skill, but it needs review because it can send API keys and trip/location queries to an environment-configured endpoint without validation.

Review this before installing if you will use real home, work, customer, or travel locations. Only run it with a trusted AMAP_BASE_URL, preferably the default AMap endpoint, and understand that route and POI requests send location data plus your AMap API key to the configured service.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/navigation.js:12
Finding
Unvalidated API Base URL Can Exfiltrate API Keys and Travel Data in Route Planning<![CDATA[ ## Vulnerability Details **File Location**: `scripts/navigation.js`, lines 12-13 and 35-57; the same unvalidated base URL is reused for route requests at lines 83-110 **Vulnerability Type**: Unvalidated external service endpoint / sensitive-data exfiltration **Risk Level**: Medium ### Vulnerable Code ```javascript const AMAP_API_KEY = process.env.AMAP_API_KEY || 'demo_key'; const AMAP_BASE_URL = process.env.AMAP_BASE_URL || 'https://restapi.amap.com'; /** * Geocoding: converts an address to coordinates */ async function geocode(address) { const url = new URL('/v3/geocode/geo', AMAP_BASE_URL); url.searchParams.set('key', AMAP_API_KEY); url.searchParams.set('address', address); return new Promise((resolve, reject) => { https.get(url.toString(), (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { const result = JSON.parse(data); if (result.status === '1' && result.geocodes && result.geocodes.length > 0) { resolve(result.geocodes[0].location); } else { reject(new Error(`Geocoding failed: ${address}`)); } } catch (err) { reject(err); } }); }).on('error', reject); }); } ``` Route requests use the same configuration: ```javascript const endpoint = mode === 'transit' ? '/v3/direction/transit/integrated' : `/v3/direction/${mode}`; const url = new URL(endpoint, AMAP_BASE_URL); url.searchParams.set('key', AMAP_API_KEY); url.searchParams.set('origin', originLoc); url.searchParams.set('destination', destLoc); https.get(url.toString(), (res) => { // Response processing }); ``` ### Technical Analysis `AMAP_BASE_URL` is read directly from the process environment and used as the base for outbound HTTPS requests without validating its hostname, port, credentials, or expected origin. The code then places the AMap API key and user travel information in URL query parameters. ...[truncated 1606 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the configurable base URL if endpoint customization is unnecessary. 2. If customization is required, parse and validate the configured URL before any request: - Require the `https:` protocol. - Allow only the exact hostname `restapi.amap.com`, or another explicit approved-host allowlist. - Reject embedded credentials, fragments, unexpected ports, and unapproved subdomains. 3. Construct requests from a fixed trusted origin and append only known API paths. 4. Avoid placing credentials in query strings where the upstream API supports secure authorization headers. 5. Ensure launchers and deployment systems prevent untrusted users from modifying the Skill's environment. 6. Apply request timeouts and response-size limits as defense-in-depth measures. 7. Rotate the AMap API key if execution with an untrusted `AMAP_BASE_URL` may already have occurred. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/poi_search.js:11
Finding
Unvalidated POI API Endpoint Can Exfiltrate API Keys and Location Queries<![CDATA[ ## Vulnerability Details **File Location**: `scripts/poi_search.js`, lines 11-12, 44-68, and 75-97 **Vulnerability Type**: Unvalidated external service endpoint / sensitive-data exfiltration **Risk Level**: Medium ### Vulnerable Code ```javascript const AMAP_API_KEY = process.env.AMAP_API_KEY || 'demo_key'; const AMAP_BASE_URL = process.env.AMAP_BASE_URL || 'https://restapi.amap.com'; const url = new URL('/v5/place/around', AMAP_BASE_URL); url.searchParams.set('key', AMAP_API_KEY); url.searchParams.set('keywords', keyword || ''); url.searchParams.set('location', centerLoc); url.searchParams.set('radius', radius); if (type && POI_TYPES[type]) { url.searchParams.set('types', POI_TYPES[type]); } url.searchParams.set('sortrule', sort === 'rating' ? 'weight' : 'distance'); url.searchParams.set('page_size', Math.min(limit, 25)); return new Promise((resolve, reject) => { https.get(url.toString(), (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { const result = JSON.parse(data); resolve(formatPOIResult(result)); } catch (err) { reject(err); } }); }).on('error', reject); }); ``` The geocoding operation is affected in the same way: ```javascript async function geocode(address) { const url = new URL('/v3/geocode/geo', AMAP_BASE_URL); url.searchParams.set('key', AMAP_API_KEY); url.searchParams.set('address', address); return new Promise((resolve, reject) => { https.get(url.toString(), (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { const result = JSON.parse(data); if (result.status === '1' && result.geocodes && result.geocodes.length > 0) { resolve(result.geocodes[0].location); } else { reject(new Error(`Geocoding failed: ${address}`)); } } catch (err) { reject(err); } }); ...[truncated 1648 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use a fixed AMap API origin rather than an environment-controlled base URL. 2. If endpoint configuration must remain available: - Require `https:`. - Compare the parsed hostname against an exact allowlist. - Reject unexpected ports, URL credentials, fragments, and lookalike subdomains. 3. Keep approved API paths in code and do not permit callers to supply arbitrary request origins. 4. Protect the execution environment so untrusted users and inputs cannot define `AMAP_BASE_URL`. 5. Minimize transmitted location data and document when addresses and coordinates are sent to AMap. 6. Add network timeouts, maximum response sizes, and HTTP status validation. 7. Rotate potentially disclosed API keys and monitor their usage for unexpected traffic. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/taxi_estimate.js:11
Finding
Unvalidated Taxi Estimation Endpoint Can Exfiltrate API Keys and Trip Details<![CDATA[ ## Vulnerability Details **File Location**: `scripts/taxi_estimate.js`, lines 11-12, 29-53, and 61-83 **Vulnerability Type**: Unvalidated external service endpoint / sensitive-data exfiltration **Risk Level**: Medium ### Vulnerable Code ```javascript const AMAP_API_KEY = process.env.AMAP_API_KEY || 'demo_key'; const AMAP_BASE_URL = process.env.AMAP_BASE_URL || 'https://restapi.amap.com'; const url = new URL('/v3/direction/driving', AMAP_BASE_URL); url.searchParams.set('key', AMAP_API_KEY); url.searchParams.set('origin', originLoc); url.searchParams.set('destination', destLoc); return new Promise((resolve, reject) => { https.get(url.toString(), (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { const result = JSON.parse(data); if (result.status === '1' && result.route && result.route.paths) { const path = result.route.paths[0]; resolve({ distance: parseFloat(path.distance), duration: parseFloat(path.duration) }); } else { reject(new Error('Distance calculation failed')); } } catch (err) { reject(err); } }); }).on('error', reject); }); ``` Addresses are also sent through the same unvalidated origin: ```javascript async function geocode(address) { const url = new URL('/v3/geocode/geo', AMAP_BASE_URL); url.searchParams.set('key', AMAP_API_KEY); url.searchParams.set('address', address); return new Promise((resolve, reject) => { https.get(url.toString(), (res) => { let data = ''; res.on('data', chunk => data += chunk); res.on('end', () => { try { const result = JSON.parse(data); if (result.status === '1' && result.geocodes && result.geocodes.length > 0) { resolve(result.geocodes[0].location); } else { reject(new Error(`Geocoding failed: ${address}`)); } } catch ...[truncated 1727 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace `AMAP_BASE_URL` with a fixed trusted constant when endpoint overrides are not operationally required. 2. Otherwise, validate the parsed endpoint before constructing requests: - Permit only HTTPS. - Require an exact approved hostname. - Reject custom credentials, fragments, nonstandard ports, and unapproved hosts. 3. Restrict who can modify the Skill process environment and deployment configuration. 4. Avoid logging full request URLs because they contain credentials and sensitive coordinates. 5. Use authorization headers instead of query-string credentials if supported by the service. 6. Introduce request timeouts, response-size limits, and HTTP status checks. 7. Rotate the API key and review usage logs if an untrusted endpoint may previously have been configured. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (23)

Ae1

High
Category
analysis-evasion
Content
node scripts/navigation.js \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/navigation.js \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/navigation.js \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/navigation.js \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/navigation.js \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/poi_search.js \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/poi_search.js \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/poi_search.js \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/taxi_estimate.js \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
node scripts/taxi_estimate.js \
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Credential Access

High
Category
Privilege Escalation
Content
{
  "status": "error",
  "code": "INVALID_API_KEY",
  "message": "请在 .env 文件中配置有效的 AMAP_API_KEY"
}

// 无可用路线
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README describes location search, route planning, traffic, and taxi estimation features but does not disclose that user-supplied origin/destination, POI, and travel data will be transmitted to external map providers such as Amap. This creates a transparency and privacy-consent gap because users may unknowingly expose sensitive location or movement information to third parties.

Natural-Language Policy Violations

Medium
Confidence
82% confidence
Finding
The manifest sets "region": "CN", and the description and tags are all China-specific, but the file does not indicate that users can choose another locale or explicitly opt into this regional constraint. Under the policy, forcing a specific language or locale without user opt-in can be a natural-language policy violation unless the constraint is clearly documented and justified.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The skill's comments and especially its CLI/error/output strings are written only in Chinese, including usage and failure messages. This creates a language policy concern because the skill imposes a specific locale without offering the user any choice or documented opt-in.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The geocoding function sends user-supplied address/location data to the external AMap API, which is a real privacy issue if users are not clearly informed that their origin and destination will leave the local environment. In a navigation skill this data is expected for functionality, but undisclosed transmission of sensitive location information can expose home, work, or travel patterns to a third party.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The script sends user-supplied location or address data to the external Amap service for geocoding and POI lookup without any notice, consent flow, or minimization controls. Location data is sensitive personal information, and transmitting it to a third party can create privacy, compliance, and user-trust risks, especially if this skill is embedded in a larger agent workflow where users may not realize their data leaves the local environment.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
This code file contains user-facing natural-language strings and comments that assume Chinese as the only language, starting with the header and continuing throughout output messages. The policy requires flagging language or locale constraints when the skill forces a specific language without user opt-in, and no user language choice or region-specific justification is provided here.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The script sends user-supplied origin and destination data to an external Amap geocoding/routing service, which can expose sensitive location or address information to a third party. There is no clear user-facing notice, consent flow, or data-handling disclosure, so users may unknowingly transmit personal travel data outside the local environment.

Natural-Language Policy Violations

Low
Confidence
76% confidence
Finding
文件中的标题、说明和使用示例注释均为中文,没有提供其他语言选项,也未说明该技能仅面向中文用户或特定区域。按规则,若技能默认强制特定语言且未提供用户选择或合理说明,可视为自然语言层面的语言/区域策略问题。

Natural-Language Policy Violations

Low
Confidence
90% confidence
Finding
The skill title, category, and region metadata indicate a China-specific navigation assistant and all trigger/examples are presented only in Chinese. Under the policy rule, forcing a specific language or locale without explicit user opt-in can be a natural-language policy violation unless the locale restriction is clearly documented and justified as region-specific.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
The file’s description and all user-facing messages are in Chinese, which imposes a specific language on users. Under the policy, locale or language constraints should either be optional for the user or clearly justified as region-specific; this demo script does not provide that opt-in or justification.

Natural-Language Policy Violations

Low
Confidence
89% confidence
Finding
Natural-language strings, category names, and CLI help are exclusively in Chinese, and the POI type mapping expects Chinese inputs only. There is no indication that this locale restriction is optional, configurable, or explicitly justified as a region-specific tool.

Natural-Language Policy Violations

Low
Confidence
88% confidence
Finding
User-facing strings, comments describing purpose, error messages, and usage text are all in Chinese, and the script does not provide any opt-in or configurable language selection. Under the policy, forcing a specific language without user choice can be a natural-language policy violation unless clearly justified as region-specific.