Back to skill

Security audit

获取一嗨租车的租车价格

Security checks for vulnerabilities and agentic risk

Overview

The skill is coherent for OneHai rental-price lookup, but it needs Review because it automates a logged-in Chrome session and has a confirmed code flaw that could run unintended page scripts.

Install only if you are comfortable with an agent automating your logged-in OneHai Chrome session. Use it for explicit China rental-price requests, avoid passing untrusted city or location text until the JavaScript interpolation bug is fixed, and be aware that output may include a snippet of authenticated booking-page text.

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/query-onehai-live-chrome.mjs:163
Finding

JavaScript Injection Through Unescaped City Arguments in Authenticated Chrome

Content
View full analysis

Vulnerability Details

File Location: scripts/query-onehai-live-chrome.mjs, lines 163–182
Vulnerability Type: JavaScript injection caused by unsafe string interpolation
Risk Level: High

Vulnerable Code

js
if (!pickupCity) {
  return JSON.stringify({ ok: false, reason: "一嗨站内城市列表未找到 ${query.pickup.city}。" });
}
if (!dropoffCity) {
  return JSON.stringify({ ok: false, reason: "一嗨站内城市列表未找到 ${query.dropoff.city}。" });
}

var pickupStores = JSON.parse(post("https://www.1hai.cn/Premises/RegionalStore", { cityId: pickupCity.cityId })).data || [];
var queryScene = ${JSON.stringify(query.pickup.scene)};
var pickupStore = pickStore(pickupStores, ${JSON.stringify(query.pickup.location)});
if (!pickupStore) {
  return JSON.stringify({ ok: false, reason: "${query.pickup.city} 当前未返回可预订门店。" });
}

var returnStore = pickupStore;
if (${JSON.stringify(query.dropoff.city !== query.pickup.city || Boolean(query.dropoff.location))}) {
  var returnStores = JSON.parse(post("https://www.1hai.cn/Premises/RegionalStore", { cityId: dropoffCity.cityId })).data || [];
  queryScene = ${JSON.stringify(query.dropoff.scene)};
  returnStore = pickStore(returnStores, ${JSON.stringify(query.dropoff.location)});
  if (!returnStore) {
    return JSON.stringify({ ok: false, reason: "${query.dropoff.city} 当前未返回可预订还车门店。" });
  }
}

The relevant input normalization in scripts/query.mjs, lines 4–6, does not escape JavaScript metacharacters:

js
function normalizeString(value) {
  return value === undefined || value === null ? "" : String(value).trim();
}

Technical Analysis

The skill constructs JavaScript as a template string and executes it in a OneHai browser tab through AppleScript. Pickup and drop-off city values originate from command-line arguments and may ultimately reflect user-provided rental-search parameters.

Although most dynamic values in buildResolveBookingJavaScript() are safely serialized with JSON.stringify(), four city-name occurrences are ...[truncated 2643 chars]

Remediation
View remediation

Remediation Suggestions

  1. Never insert raw user-controlled values into generated JavaScript source. Serialize every city value with JSON.stringify() before including it in the script.

  2. Define safely serialized variables once and use concatenation inside static JavaScript:

js
const pickupCityLiteral = JSON.stringify(query.pickup.city);
const dropoffCityLiteral = JSON.stringify(query.dropoff.city);

return `
(function () {
  var requestedPickupCity = ${pickupCityLiteral};
  var requestedDropoffCity = ${dropoffCityLiteral};

  // ...

  if (!pickupCity) {
    return JSON.stringify({
      ok: false,
      reason: "OneHai did not contain the requested pickup city: " +
        requestedPickupCity
    });
  }

  if (!dropoffCity) {
    return JSON.stringify({
      ok: false,
      reason: "OneHai did not contain the requested drop-off city: " +
        requestedDropoffCity
    });
  }
})()
`;
  1. Apply the same safe serialization pattern to all four affected error messages, including the pickup-store and return-store branches.

  2. Prefer separating code from data entirely. Keep the browser JavaScript static and pass query data through a serialized JSON object:

js
const serializedQuery = JSON.stringify(query);

return `
(function (query) {
  // Static implementation using query.pickup.city and query.dropoff.city.
})(${serializedQuery})
`;
  1. Validate city values against a strict format and reasonable length before generating browser code. This is defense in depth and must not replace contextual serialization.

  2. Add regression tests containing quotes, backslashes, line terminators, template-string syntax, and JavaScript fragments. Verify that these values remain data and cannot alter the generated program’s syntax.

  3. Audit every future interpolation in generated AppleScript and browser JavaScript according to its destination context. JavaScript values should use JSON serialization; AppleScript arguments should continue to be passed through ar ...[truncated 50 chars]

Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (14)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 32)May include surrounding context.

md
3. Run `scripts/query-onehai-live-chrome.mjs`.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
84% confidence
Finding

The skill clearly describes live querying of OneHai through the user's logged-in Chrome session, which implies account-backed browser automation and network access, yet it declares no explicit tool scope or permissions boundary. That mismatch increases the risk of overbroad execution and weak user awareness about what capabilities the skill will exercise.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This skill relies on the user's logged-in Chrome session plus Apple Events JavaScript automation to access rental data tied to an authenticated account, but the user-facing description does not prominently warn about that sensitive access path. Without explicit disclosure and consent, a user may trigger browsing actions against their session without understanding that account context, cookies, and potentially personal booking data are being used.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill enables implicit invocation with no visible activation constraints, so the agent may trigger it broadly based on loose relevance rather than explicit user intent. In this skill's context, that is riskier because it is described as using the user's logged-in Chrome session on macOS to query a third-party service, which can cause unintended use of authenticated state and accidental external interactions.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill logic relies on Chinese-only regex patterns for location inference and later emits Chinese warning text, which effectively constrains behavior to a specific language/locale. There is no visible opt-in, fallback, or documentation in this file indicating that the skill is intentionally region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

Functions such as parseOneHaiInventoryCount, parseOneHaiPeakRentalRule, and buildOneHaiPeakRentalHint assume Chinese text formats and produce Chinese-language warnings. This is a language/locale policy concern because the file forces a specific language behavior without showing user choice or an explicit justified locale constraint.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest frames the skill as using the user's logged-in Chrome session to query OneHai and return reference prices. While driving Chrome is consistent with that purpose, the code also executes native macOS AppleScript and an external OCR binary, which are broader host-execution capabilities not explicitly justified by a rental-price lookup skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script captures and returns booking page body text, title, URL, and vehicle card contents from a logged-in Chrome session, then emits a preview slice of that content. Because this operates against an authenticated user session, the output can expose account-linked booking information or other sensitive page data beyond the minimum needed for pricing.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The formatDurationMinutes function hard-codes Chinese output strings (天, 小时, 分) for all users. This imposes a specific language/locale in code without any visible opt-in, configurability, or documented region-specific justification, which matches the language-policy violation criteria.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The instruction to "Keep the wording as 参考实时价" mandates a specific language output. This is a language/locale policy concern because the file does not offer a user language preference or explain why Chinese-only phrasing is required.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The natural-language instruction is written as a fixed English prompt ('Use $china-rental-price...') while the skill name and description target Chinese users and context. This may create a language-policy concern if the skill implicitly constrains interaction language without opt-in or documented justification.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The extraction logic only recognizes RMB/CNY symbols and Chinese text patterns such as '元', '/天', and '每天', and later uses Chinese vehicle labels. This imposes a specific locale/language behavior in the skill logic without any visible opt-in or user-selectable locale handling in this file.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The manifest describes retrieving reference prices and booking URLs from OneHai using the user's Chrome session. This implementation additionally decodes canvas image data, writes PNGs to a temp directory, and processes them locally, which extends the skill into host file-system and OCR operations not mentioned in the stated purpose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The code writes image data derived from the authenticated booking page to disk before OCR without any visible disclosure or consent flow in this file. Even though the files are temporary, they may contain pricing or session-derived page artifacts and create avoidable local data exposure on the host system.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.