Back to skill

Security audit

甩手店长一键采集,刊登

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent MCP client, but it gives broad production access to live shop actions while caching credentials and forwarding them with weak safeguards.

Install only if you trust the htyd production MCP service and are comfortable giving this client authority to access shop data and publish products. Prefer environment-provided, revocable credentials, avoid changing MCP_URL to untrusted or HTTP endpoints, check or remove ~/.htyd-mcp-client-streamable.json after use, and require explicit human confirmation before any collect/claim/publish command.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/htyd-mcp.mjs:25
Finding

Authorization Credential Stored in a Plaintext File Without Restrictive Permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/htyd-mcp.mjs, lines 25–32 and 74–81
Vulnerability Type: Plaintext storage of sensitive authentication credentials
Risk Level: Medium

Vulnerable Code

js
function safeWriteJson(filePath, obj) {
  try {
    fs.writeFileSync(filePath, JSON.stringify(obj, null, 2), "utf8");
  } catch {
    // ignore
  }
}

The authorization value is passed directly to this function:

js
const configPath = getConfigFilePath();
const cfg = safeReadJson(configPath) ?? {};
const fromFile = !forcePrompt && typeof cfg.authorization === "string" ? cfg.authorization.trim() : "";
if (fromFile) return { Authorization: fromFile };

const authorization = await promptForAuthorization();
if (!authorization) return {};

safeWriteJson(configPath, { ...cfg, authorization });
return { Authorization: authorization };

Technical Analysis

The client persists the complete bearer token or authorization header in ~/.htyd-mcp-client-streamable.json as plaintext. The call to fs.writeFileSync does not specify a restrictive file mode, such as 0o600.

On POSIX systems, a newly created file consequently uses the runtime's default creation mode subject to the process umask. Under a common umask of 022, this can produce a file readable by other local users. If the file already exists with unsafe permissions, the implementation neither detects nor repairs those permissions. On other operating systems, protection depends entirely on inherited directory and account access-control settings.

The empty catch block also suppresses storage and permission-related errors, preventing the user from knowing whether the credential was stored safely.

Attack Path

  1. The user starts the client without setting MCP_APP_KEY or MCP_AUTHORIZATION.
  2. The client prompts the user for an AppKey or complete authorization value.
  3. The credential is normalized and ...[truncated 1118 chars]
Remediation
View remediation

Remediation Suggestions

  1. Store long-lived credentials in the operating system's credential manager, such as Windows Credential Manager, macOS Keychain, or a Linux secret service.

  2. If file storage is unavoidable, create the file with owner-only permissions:

    js
    fs.writeFileSync(
      filePath,
      JSON.stringify(obj, null, 2),
      { encoding: "utf8", mode: 0o600 }
    );
    
  3. Create the parent directory with mode 0o700 where POSIX permissions are supported.

  4. Inspect existing file permissions before reading credentials and reject or repair files accessible by group or other users.

  5. Avoid persisting the complete Authorization header when a shorter-lived or revocable token can be used.

  6. Provide an option that disables credential persistence entirely.

  7. Report write and permission failures to the user rather than silently suppressing them.

  8. Document credential rotation and revocation procedures in case the configuration file is exposed.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/htyd-mcp.mjs:509
Finding

Authorization and Login Credentials Can Be Sent to an Arbitrary or Plaintext HTTP Endpoint

Content
View full analysis

Vulnerability Details

File Location: scripts/htyd-mcp.mjs, lines 8–11, 69–82, and 509–526
Vulnerability Type: Insecure transport and credential forwarding to an untrusted endpoint
Risk Level: Medium

Vulnerable Code

The endpoint is accepted directly from the environment:

js
function getMcpUrl() {
  return process.env.MCP_URL ?? "https://dz.shuaishou.com/mcp";
}

Stored or environment-provided authorization is automatically reused:

js
async function getAuthHeadersInteractive({ forcePrompt = false } = {}) {
  const fromEnv = envAuthorization();
  if (!forcePrompt && fromEnv) return { Authorization: fromEnv };

  const configPath = getConfigFilePath();
  const cfg = safeReadJson(configPath) ?? {};
  const fromFile = !forcePrompt && typeof cfg.authorization === "string" ? cfg.authorization.trim() : "";
  if (fromFile) return { Authorization: fromFile };

  const authorization = await promptForAuthorization();
  if (!authorization) return {};

  safeWriteJson(configPath, { ...cfg, authorization });
  return { Authorization: authorization };
}

Both HTTPS and plaintext HTTP are supported, and the authorization headers are attached without endpoint validation:

js
async post(body, expectedId) {
  const url = new URL(this.mcpUrl);
  const client = url.protocol === "https:" ? https : http;
  const acceptHeader = "application/json, text/event-stream";
  return await new Promise((resolve, reject) => {
    const req = client.request(
      url,
      {
        method: "POST",
        headers: {
          ...this.headers,
          ...(this.sessionId ? { "Mcp-Session-Id": this.sessionId } : {}),
          Accept: acceptHeader,
          "Content-Type": "application/json",
          "Content-Length": Buffer.byteLength(body),
        },
      },

Technical Analysis

MCP_URL is not restricted to HTTPS and is not validat ...[truncated 3002 chars]

Remediation
View remediation

Remediation Suggestions

  1. Reject all non-HTTPS endpoints by default:

    js
    const url = new URL(this.mcpUrl);
    if (url.protocol !== "https:") {
      throw new Error("MCP_URL must use HTTPS");
    }
    
  2. Permit plaintext HTTP only through an explicit development-only override, accompanied by a prominent warning and with authorization disabled.

  3. Bind persisted credentials to the endpoint's normalized scheme, hostname, and port. Do not reuse a credential when the endpoint changes.

  4. Require explicit user confirmation before sending credentials to a host other than the production host.

  5. Consider an allowlist for approved MCP hosts in production deployments.

  6. Reject URLs containing embedded usernames or passwords and reject unsupported protocols.

  7. Do not send a cached production credential to development, testing, or user-specified endpoints.

  8. Before accepting service login credentials, display the destination host and require HTTPS.

  9. Use short-lived, revocable, and narrowly scoped tokens to reduce the impact of disclosure.

  10. Document that changing MCP_URL changes the recipient of authorization headers and all business or login request data.

Vulnerability Patterns
  • 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 Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (11)

Unrestricted Tool Access

Medium
Category
Excessive Agency
Confidence
84% confidence
Finding

The skill advertises the ability to connect to a production MCP endpoint and invoke all available tools, including login, without documenting any allowlist, approval boundary, or least-privilege restriction. In this context, broad dynamic tool access is dangerous because newly exposed or sensitive server-side tools could be invoked unintentionally or abused through this wrapper, especially against a production system.

Content

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

md
---
name: htyd-mcp-client-streamable
description: Builds and uses an MCP client (Streamable HTTP transport) to connect to the htyd MCP server and invoke all available tools (including login). Use when connecting to a Streamable HTTP MCP endpoint like https://dz.shuaishou.com/mcp. This is the production version.
---

# HTYD MCP Client (Streamable HTTP) - Production

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill explicitly states that missing API credentials may be entered interactively and then persisted to a local file for automatic reuse. Storing authentication material on disk without a clear warning, consent flow, storage protections, or guidance on file permissions creates a real risk of credential exposure to other local users, backup systems, or malware on the host.

Content

No source excerpt is available for this finding.

Unrestricted Tool Access

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Advertising 'Call any tool' signals unrestricted access to all MCP-exposed operations, including login and potentially state-changing functions. In the context of a production MCP endpoint and business workflows that can publish listings, this weakens least-privilege expectations and increases the chance of misuse, overbroad agent behavior, or invocation of unsafe tools without adequate gating.

Content

Scanner excerpt · scripts/README.md (reported line 22)May include surrounding context.

node htyd-mcp.mjs tools

text

Call any tool:

```bash
node htyd-mcp.mjs call list_shops "{}"

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README expands the skill from a generic MCP client into concrete high-impact business automation for collecting, claiming, and publishing products. That scope expansion matters because it encourages operational use cases with external side effects that are not clearly bounded by the manifest description, increasing the risk that an agent or operator invokes publishing actions without appreciating their business impact.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README presents a one-step collect-and-publish workflow without prominently warning that it performs a consequential external action: listing goods to a shop. This is especially risky because the flow ends when the publish API is sent and does not verify async outcome, which can mislead operators into treating the action as routine while still causing real marketplace changes.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The guidance says to use this command for requests like 'publish this link to shop' or 'collect and publish to shop,' which are broad natural-language triggers for a sensitive action. Without tighter constraints or confirmation requirements, an agent could map ambiguous user phrasing directly to a publish workflow that changes marketplace state.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code defines a fixed credential/config file in the user's home directory for this client, creating a predictable location for sensitive authorization data. Predictable plaintext secret storage broadens exposure to local attackers, malware, accidental check-ins, shell-history-like discovery, and insecure backup/sync processes.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script does more than simply invoke MCP tools: it interactively requests authorization material and persists it locally for later reuse. Storing bearer tokens or app keys without explicit consent, secure storage, or file-permission controls increases the risk of credential disclosure from local compromise, backups, or other processes reading the file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

When a user types an AppKey or Authorization header interactively, the script silently writes that credential to disk. This is dangerous because users may reasonably expect prompted secrets to be used ephemerally, and undisclosed persistence can lead to long-lived credential exposure and reuse by anyone with local file access.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

The document contains substantial Chinese-only operational guidance and examples, starting with a Chinese production notice, without stating that users may request another language. This can violate language/locale policy when a skill implicitly forces a specific language without opt-in.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The file contains user-facing comments and runtime messages in Chinese only, including prompts and status/error output later in the script. For a general-purpose CLI skill, this imposes a specific language/locale on users without offering a choice or documenting a justified locale restriction.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.