Back to skill

Security audit

ZhenInsure 真机保险 | Insurance Broker

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly behaves like a disclosed insurance chat API proxy, but it can be configured to send the user's API key and sensitive consultation data to an arbitrary base URL.

Install only if you trust the publisher and can control the runtime configuration. Before use, verify that ZHENINSURE_BASE_URL is unset or restricted to an approved ZhenInsure origin, treat the API key as a production secret, and avoid sending real health, financial, or customer data unless you have consent and understand ZhenInsure's data handling terms.

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
actions/proxy.js:52
Finding

Unrestricted Base URL Override Exposes API Credentials and Conversation Data

Content
View full analysis

Vulnerability Details

File Location: actions/proxy.js:52-56, 105, 110-116
Vulnerability Type: Unvalidated outbound request destination / credential disclosure
Risk Level: High

Vulnerable Code

js
const baseUrl = normBase(
  context?.config?.ZHENINSURE_BASE_URL ??
  context?.env?.ZHENINSURE_BASE_URL ??
  process.env.ZHENINSURE_BASE_URL
);
js
const url = `${baseUrl}${endpoint}`;

let res;
try {
  const ctl = new AbortController();
  const timer = setTimeout(() => ctl.abort(), REQUEST_TIMEOUT_MS);
  res = await fetch(url, {
    method,
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${apiKey}`,
      "User-Agent": `ZhenInsure-Skill/${SKILL_VERSION}`,
      Accept: "application/json",
    },
    body: method === "POST" && body ? JSON.stringify(body) : undefined,
    signal: ctl.signal,
  });

Technical Analysis

The proxy restricts endpoint paths and HTTP methods, but it does not restrict the destination origin. ZHENINSURE_BASE_URL may come from action context configuration, context environment data, or the process environment. The normBase function only trims whitespace and trailing slashes; it does not enforce HTTPS, verify the hostname, restrict ports, or require the official ZhenInsure origin.

The proxy subsequently sends the live ZHENINSURE_API_KEY in an Authorization header and forwards the request body to the selected origin. Consequently, anyone able to influence the base URL can redirect credentials and insurance consultation data to an attacker-controlled server.

This behavior exceeds the minimum privileges declared in SKILL.md, which states that requests are forwarded directly to https://www.zhenins.com. The custom-origin behavior is explicitly covered by tests in test/test-all.js:414-462, including configuration and process-environment overrides.

Attack Path

  1. An attacker, compromised ...[truncated 1444 chars]
Remediation
View remediation

Remediation Suggestions

  1. Remove the runtime base-URL override from production builds and always use the fixed official origin:

    js
    const baseUrl = "https://www.zhenins.com";
    
  2. If staging support is operationally required, parse the value with new URL() and enforce:

    • https: only.
    • An exact hostname allowlist.
    • Approved ports only.
    • No embedded username or password.
    • No query string or fragment in the configured base URL.
    • A normalized origin rather than arbitrary URL concatenation.
  3. Use separate credentials for production and staging so a production key is never sent to a non-production origin.

  4. Disable automatic cross-origin redirects or verify the final destination before forwarding an authorization header. Sensitive authorization headers must never be forwarded to an unapproved redirect target.

  5. Ensure environment and action-context configuration cannot override the trusted destination unless controlled by an authorized administrator.

  6. Add negative tests proving that the proxy rejects:

    • Plaintext HTTP URLs.
    • Unapproved domains.
    • Look-alike and subdomain-suffix hosts.
    • Embedded credentials.
    • Unexpected ports.
    • Redirects to unapproved origins.
  7. Update the documentation to accurately disclose any approved staging behavior and its credential-separation requirements.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (9)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The guide explicitly shows configuring a live API key (sk_live_abc123...) without any warning about credential sensitivity, secret storage, shell history exposure, or least-privilege handling. In a publishing/install guide, this can normalize unsafe secret handling practices and increase the chance that users paste production credentials into insecure environments, logs, screenshots, or shared terminals.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README explicitly demonstrates sending highly sensitive health information (for example, hypertension status and age) to a remote cloud API, but provides no privacy notice, consent guidance, data-handling explanation, or warning about transmitting special-category personal data. In an insurance context, this data is especially sensitive because it can affect underwriting and eligibility decisions, so users need clear disclosure before use.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill is explicitly designed as a transparent proxy that forwards user-supplied conversation content to an external backend while automatically attaching the operator's API key. The documentation describes this data flow but does not warn users that their messages and identifiers will leave the local environment and be processed by a third-party service, which creates a meaningful privacy and consent risk, especially for insurance-related conversations that may include sensitive personal or health information.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill returns user-facing error and action text in Chinese, and this pattern continues throughout the file. The policy requires flagging language or locale constraints when the skill forces a specific language without user opt-in or clear justification.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest explicitly proxies insurance consultation chats and human handoff, which implies transmission of sensitive personal and potentially health-related data to a third-party service. Yet the skill description and parameters provide no user-facing warning, consent notice, retention statement, or data-sharing disclosure, increasing the risk that users disclose regulated or highly sensitive information without informed consent.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This JavaScript test file contains multiple assertions that require response messages to include Chinese text such as "未配置", "端点不可用", "成功", and similar phrases. That encodes a single-language requirement into the skill behavior, which is a natural-language locale policy concern when no user opt-in or documented justification is present in the file.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · test/test-all.js (reported line 437)May include surrounding context.

js
queueFetchResponse(200, {});

  await proxy({
    config: { ZHENINSURE_BASE_URL: "https://api.zhenins.com/" },
    args: { endpoint: "/api/v1/skill/chat/conversations", method: "POST" },
    secrets: { ZHENINSURE_API_KEY: "sk_live_12345678901234567890123456789012" },
  });

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · test/test-all.js (reported line 443)May include surrounding context.

js
queueFetchResponse(200, {});

  await proxy({
    config: { ZHENINSURE_BASE_URL: "https://api.zhenins.com/" },
    args: { endpoint: "/api/v1/skill/chat/conversations", method: "POST" },
    secrets: { ZHENINSURE_API_KEY: "sk_live_12345678901234567890123456789012" },
  });

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The natural-language instructions, feature descriptions, and usage guidance are presented only in Chinese. Under the policy, forcing a specific language without user opt-in or a documented justification can be a locale-policy violation.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access, suspicious.exposed_secret_literal

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
actions/proxy.js:13

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
test/test-all.js:215