Back to skill

Security audit

九号数据展示

Security checks for vulnerabilities and agentic risk

Overview

This skill is a disclosed read-only Ninebot vehicle reporting helper, with expected handling of local vehicle data and map services.

Install only if you are comfortable letting a local agent read your Ninebot vehicle status, rides, and location through an already authenticated ninecli session. Map and ride-visualization features may send location or route-area data to third-party map services; use privacy=off or avoid map commands if that is not acceptable.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (37)

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

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

md
# Ninebot Show Skill

Read-only Agent Skill for Ninebot/九号 electric vehicles. It uses a locally authenticated `ninecli` session. Never ask the user to paste a Ninebot password, SMS verification code, access token, cookie, or BLE secret into chat.

## Use this skill for

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/runtime_config.py (reported line 41)May include surrounding context.

python
return value

    explicit = os.environ.get("NINEBOT_ENV_FILE", "").strip()
    candidates = [Path(explicit).expanduser()] if explicit else [CONFIG_DIR / ".env"]
    for env_file in candidates:
        try:
            lines = env_file.read_text(encoding="utf-8", errors="ignore").splitlines()

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 61)May include surrounding context.

md
# Optional. Copy to ~/.config/ninebot-show-skill/.env and fill locally.
AMAP_WEB_KEY=

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · templates/env.example (reported line 1)May include surrounding context.

text
# Optional. Copy to ~/.config/ninebot-show-skill/.env and fill locally.
AMAP_WEB_KEY=

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill documentation is written entirely in Chinese, including setup and operational instructions, with no indication that another language is supported or that the Chinese-only presentation is an intentional, justified locale constraint. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises shell, network, file read/write, and environment access but does not declare any explicit tool scope or allowed-tools boundary. That creates unnecessary ambient authority: an agent platform may grant broader capabilities than needed, increasing the chance of unintended command execution, local file access, or data exfiltration if the skill is invoked in the wrong context.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

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

md
# Ninebot Show Skill

Read-only Agent Skill for Ninebot/九号 electric vehicles. It uses a locally authenticated `ninecli` session. Never ask the user to paste a Ninebot password, SMS verification code, access token, cookie, or BLE secret into chat.

## Use this skill for

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

.venv/bin/ninecli vehicles --json

text

Write the returned vehicle `wnumber` into:

```text
~/.config/ninebot-show-skill/config.json

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The installer copies the skill into agent-specific directories and immediately executes a setup script from that copied location without any prompt, dry-run, or explicit disclosure of what setup will do. Even though this is a common installation pattern, it creates a trust boundary problem: running install.sh implicitly runs additional code, which increases the chance of unintended local changes or abuse if the package contents are modified or the user expects a copy-only install.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/locate.py (reported line 69)May include surrounding context.

python
def read_status(sn: str) -> tuple[dict, float, float]:
    out = subprocess.run(ninecli_argv(SKILL_DIR, "status", sn, "--json"), capture_output=True, text=True, timeout=60)
    if out.returncode != 0:
        raise SystemExit("ninecli status 失败,请检查登录状态和 SN")
    data = json.loads(out.stdout)

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/map_shot.py (reported line 32)May include surrounding context.

python
def coords() -> tuple[float, float]:
    py = str(PYTHON if PYTHON.exists() else Path(sys.executable))
    out = subprocess.run([py, str(LOCATE), "--privacy", "coordinates", "--json"], capture_output=True, text=True, timeout=120)
    if out.returncode != 0:
        raise SystemExit(out.stderr.strip() or "定位失败")
    data = json.loads(out.stdout)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This Python file contains user-facing natural-language output, errors, help text, and report content almost entirely in Chinese, including generated report strings and CLI messages. That enforces a specific language/locale for all users without any visible opt-in, selection mechanism, or documented justification for a China-only deployment.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/ninebot_report.py (reported line 173)May include surrounding context.

python
def run_process(args: list[str], timeout: int = 35) -> subprocess.CompletedProcess[str]:
    return subprocess.run(
        args,
        capture_output=True,
        text=True,

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/render_trail.py (reported line 95)May include surrounding context.

python
def load_ride(ride_id, sn):
    raw = subprocess.run(ninecli_argv(SKILL_DIR, "travel", sn, "--detail", ride_id, "--json"),
                         capture_output=True, text=True, timeout=90).stdout
    d = json.loads(raw)
    pts = []

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/render_trail.py (reported line 111)May include surrounding context.

python
def today_ride_ids(sn):
    raw = subprocess.run(ninecli_argv(SKILL_DIR, "travel", sn, "--json"), capture_output=True, text=True, timeout=90).stdout
    d = json.loads(raw)
    today = dt.date.today()
    ids = []

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/ride_plot.py (reported line 59)May include surrounding context.

python
def latest_ride():
    out = subprocess.run(ninecli_argv(SKILL_DIR, "travel", SN, "--json"), capture_output=True, text=True, timeout=60)
    rs = json.loads(out.stdout)["list"]
    return rs[0]

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/ride_plot.py (reported line 65)May include surrounding context.

python
def ride_detail(tid):
    out = subprocess.run(ninecli_argv(SKILL_DIR, "travel", SN, "--detail", tid, "--json"),
                         capture_output=True, text=True, timeout=60)
    return json.loads(out.stdout)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The function fetches OpenStreetMap tiles based on the min/max longitude and latitude of the user's ride path, which discloses the geographic area of a recent trip to an external service. In a vehicle-status skill handling sensitive mobility data, this is a real privacy issue because home/work areas and travel habits may be inferred, and the skill description does not indicate a clear user-facing warning or consent flow for that network transmission.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script emits user-facing messages entirely in Chinese, including the error message at L12 and setup instructions through L45. This imposes a specific language on all users without any opt-in or documented locale constraint, which matches the language/locale policy violation criteria.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/setup.sh (reported line 21)May include surrounding context.

sh
"$VENV/bin/python" -m pip install -r "$SKILL_DIR/requirements.txt"

mkdir -p "$APP_CONFIG_DIR"
chmod 700 "$APP_CONFIG_DIR" 2>/dev/null || true
if [[ ! -f "$APP_CONFIG" ]]; then
  cp "$SKILL_DIR/templates/config.example.json" "$APP_CONFIG"
  chmod 600 "$APP_CONFIG" 2>/dev/null || true

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/setup.sh (reported line 24)May include surrounding context.

sh
chmod 700 "$APP_CONFIG_DIR" 2>/dev/null || true
if [[ ! -f "$APP_CONFIG" ]]; then
  cp "$SKILL_DIR/templates/config.example.json" "$APP_CONFIG"
  chmod 600 "$APP_CONFIG" 2>/dev/null || true
  echo "已创建配置: $APP_CONFIG"
else
  echo "保留现有配置: $APP_CONFIG"

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

This code hard-codes Chinese-language strings in the module docstring, error messages, and all printed status text, which imposes a specific language/locale on users. Under the policy, locale-specific behavior should either be optional via user choice or clearly documented as a justified regional constraint.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/status_card.py (reported line 39)May include surrounding context.

python
def run_json(cmd: list[str], timeout: int = 180) -> dict:
    out = subprocess.run(cmd, capture_output=True, text=True, timeout=timeout)
    if out.returncode != 0:
        raise SystemExit(out.stderr.strip() or out.stdout.strip() or "命令执行失败")
    return json.loads(out.stdout)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The example config uses a Chinese vehicle name, a Shanghai location, and an Asia/Shanghai timezone as defaults. This natural-language and locale-specific setup may steer the skill toward a specific language/region without user opt-in or justification, which matches the language/locale policy concern.

Content

No source excerpt is available for this finding.

Vague Triggers

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The manifest description says to use the skill when the user asks about 'rides, smart service, daily reports, or vehicle visualizations' without enumerating tighter trigger phrases or exclusions. Terms like 'daily reports' and 'rides' are broad enough that they could match unrelated conversation unless the surrounding system already constrains activation to Ninebot-specific context.

Content

No source excerpt is available for this finding.