Back to skill

Security audit

抖音关键词搜索采集

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated Douyin search/export purpose, but it uses risky credential transport and paid task submission controls that users should review before installing.

Install only if you are comfortable using this paid third-party collection service. Prefer configuring an HTTPS base URL before login, avoid enabling insecure TLS, review the shared config file for existing tokens, and require explicit user approval before every submit because the CLI itself will not enforce that approval.

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

Error
Location
src/config.js:20
Finding

Bearer Token Transmitted over Plaintext HTTP by Default

Content
View full analysis

Vulnerability Details

File Location: src/config.js:20, src/client.js:50-70
Vulnerability Type: Plaintext transmission of authentication credentials
Risk Level: High

Vulnerable Code

src/config.js:20:

js
const DEFAULT_BASE_URL = 'http://st.aidata366.com';

src/client.js:50-70:

js
async request(method, apiPath, opts = {}) {
  const { body, headers = {}, timeoutMs = REQUEST_TIMEOUT_MS } = opts;
  // Plain HTTP with a token only produces a warning and does not stop the request.
  if (!_httpWarned && this.token && this.baseUrl.startsWith('http://')) {
    _httpWarned = true;
    process.stderr.write('[warn] Current service address uses plaintext HTTP; token will be transmitted in plaintext\n');
  }

  const ctrl = new AbortController();
  const timer = setTimeout(() => ctrl.abort(), timeoutMs);
  let res;
  let payload = null;
  try {
    res = await fetch(this.baseUrl + '/api/v1' + apiPath, {
      method,
      headers: {
        ...(body ? { 'Content-Type': 'application/json' } : {}),
        ...(this.token ? { Authorization: `Bearer ${this.token}` } : {}),
        ...headers,
      },
      body: body ? JSON.stringify(body) : undefined,
      signal: ctrl.signal,
    });

Technical Analysis

The built-in service endpoint uses unencrypted HTTP. Authenticated API requests place the locally stored bearer token in the Authorization header and send it to that endpoint without transport encryption or authenticated TLS.

The implementation recognizes this condition but only writes a warning to stderr. It neither blocks the request nor requires explicit approval. Consequently, the default authenticated workflow exposes the token to every network segment between the client and the service.

The affected commands include quota, submit, query, export, and logout. The direct export download in cli.js:320-321 also sends the sa ...[truncated 1129 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace the default endpoint with an HTTPS URL backed by a valid certificate.
  2. Reject authenticated requests to non-HTTPS destinations rather than merely printing a warning.
  3. If HTTP is required for local development, restrict it to loopback addresses such as 127.0.0.1 and localhost.
  4. Require an explicit, narrowly scoped opt-in before allowing credentials over HTTP.
  5. Apply the same transport validation to direct export downloads and all other code paths that attach authorization headers.
  6. Avoid disabling TLS certificate validation process-wide. If self-signed certificates must be supported, use a dedicated certificate authority or per-client trust configuration.
  7. Revoke or rotate tokens that may previously have traversed the plaintext endpoint.

T09 · Insecure Skill Coding Practices

Warning
Location
cli.js:201
Finding

Paid Task Submission Does Not Enforce User Confirmation

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:37-47, cli.js:201-239
Vulnerability Type: Missing executable authorization gate for a charged operation
Risk Level: Medium

Vulnerable Code

SKILL.md:37-47 documents a confirmation requirement:

markdown
2. **Quote confirmation (required)**: Clearly provide the following information to the user and wait for confirmation before submission:
   - Search keyword, collection count, sorting, and publication-time filter
   - Estimated points
   - Billing and refund rules
   - **Do not execute submit without user confirmation.**

However, cli.js:201-239 directly performs the charged operation:

js
async function cmdSubmit(opts) {
  const cfg = resolveConfig(opts);
  requireToken(cfg);
  const keyword = validateKeyword(opts.keyword);

  if (opts.count !== undefined && !/^\d+$/.test(String(opts.count))) {
    throw new UsageError('--count must be a positive integer');
  }
  const count = opts.count !== undefined
    ? Math.max(1, Math.min(parseInt(opts.count, 10), MAX_COUNT))
    : DEFAULT_COUNT;

  const sort = SORT_WHITELIST.has(opts.sort) ? opts.sort : '0';

  if (opts.publishTime !== undefined
      && !PUBLISH_TIME_WHITELIST.has(String(opts.publishTime))) {
    throw new UsageError('--publish-time is unsupported');
  }
  const publishTime = PUBLISH_TIME_WHITELIST.has(opts.publishTime)
    ? opts.publishTime
    : '0';

  const { price } = await fetchPrice(cfg.baseUrl);
  const billUnits = ceilDiv(count, BILL_UNIT);
  const estimatedPoints = billUnits * price;

  const items = [{
    id: 1,
    payload: { keyword, count, sort, publish_time: publishTime },
  }];

  const idemSource =
    `${keyword}|${count}|${sort}|${publishTime}` +
    (opts.force ? `|#force:${Date.now()}` : '');
  const idempotencyKey = crypto.createHash('sha256')
    .update(idemSource)
    .digest('hex')
    .
...[truncated 2305 chars]
Remediation
View remediation

Remediation Suggestions

  1. Implement a two-step quote-and-confirm protocol:
    • First request a quote containing the keyword, count, filters, unit price, and total estimated charge.
    • Return a short-lived, single-use confirmation token bound to those exact values.
    • Require that token for submit.
  2. Reject submissions when the quote has expired or any charged parameter has changed.
  3. If a local confirmation flag is retained, require an unpredictable confirmation identifier rather than a generic --yes option.
  4. Enforce confirmation server-side so direct API calls cannot bypass the gate.
  5. Require a new confirmation when --force is used because it intentionally bypasses deduplication.
  6. Consider account-level spending limits and per-task maximums as defense in depth.
  7. Preserve idempotency controls, but do not treat them as a substitute for authorization.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (17)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill presents itself as a search/export tool but also reads and writes persistent local configuration and tokens under the user's home directory, and allows modifying the backend base URL. That creates credential-handling and endpoint-redirection risk that is materially more sensitive than a simple data collection utility.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill presents itself as a search/export tool but also reads and writes persistent local configuration and tokens under the user's home directory, and allows modifying the backend base URL. That creates credential-handling and endpoint-redirection risk that is materially more sensitive than a simple data collection utility.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The skill presents itself as a search/export tool but also reads and writes persistent local configuration and tokens under the user's home directory, and allows modifying the backend base URL. That creates credential-handling and endpoint-redirection risk that is materially more sensitive than a simple data collection utility.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill declares access to shell, network, and environment-like capabilities but does not constrain them with an explicit tool scope. In practice, this lets an agent invoke arbitrary CLI/network behaviors beyond the documented search workflow, increasing the blast radius if the skill is misused or the surrounding agent is prompt-injected.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The activation guidance mixes concrete actions with vague scenario labels, making it unclear when the skill should or should not run. That ambiguity increases the chance of unintended invocation and external data transfer, especially given the skill's billing model and credentialed backend usage.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The activation guidance mixes concrete actions with vague scenario labels, making it unclear when the skill should or should not run. That ambiguity increases the chance of unintended invocation and external data transfer, especially given the skill's billing model and credentialed backend usage.

Content

No source excerpt is available for this finding.

Unsafe Defaults

Medium
Category
Tool Misuse
Confidence
99% confidence
Finding

The allowInsecureTls function disables TLS certificate validation globally by setting NODE_TLS_REJECT_UNAUTHORIZED=0 for the entire process. That permits man-in-the-middle attacks against HTTPS connections, allowing interception or modification of bearer tokens, task data, exports, and any other traffic made by this process, which is especially risky for a networked data-collection skill.

Content

Scanner excerpt · src/client.js (reported line 17)May include surrounding context.

js
/** 忽略 HTTPS 证书校验 (服务端自签/域名不匹配证书时由 insecure 配置开启)。进程级。 */
function allowInsecureTls() {
  process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
}

/** 业务错误: code 为后端错误码 (1001/1002/3001/...) */

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest describes a skill for Douyin keyword-based video search result collection and CSV export. This client also exposes generic comments session APIs and Douyin comments session APIs, which support creating, stepping through, finishing, and listing comment-collection sessions—materially broader functionality than search-result collection.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This module automatically reads credentials and connection settings from another skill's legacy configuration path and copies them into this skill's config. Even if intended as convenience migration, it crosses skill boundaries and can silently reuse secrets the user did not explicitly authorize for this tool, violating least privilege and potentially sending credentials to the wrong service endpoint.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The code imports token, base_url, and insecure settings from an unrelated legacy skill context without strong proof they belong to the same backend or trust boundary. This can cause credential confusion, unintentional trust downgrades, or redirection to a legacy service, especially because the migrated insecure flag may weaken transport protections.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This JavaScript file contains natural-language comments and runtime messages exclusively in Chinese, including operational guidance and error text. Under the stated policy, forcing a specific language without user opt-in or documented locale justification is a policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The function emits user-visible stderr/stdout error guidance entirely in Chinese, such as login, retry, and billing instructions, with no evidence of locale negotiation or opt-in. This matches the policy example of a skill forcing a specific language.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code constructs new BizError(...) inside pollTask, but BizError is neither defined nor imported in this module. When the timeout path is reached, this causes a ReferenceError instead of the intended controlled business exception, which can break error handling, produce misleading output, and cause polling failures to be reported incorrectly.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
98% confidence
Finding

The file’s natural-language documentation and warning messages are entirely in Chinese, including operational warnings written to stderr. This imposes a specific language on users without any opt-in or alternative, which matches the language/locale policy violation category.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest focuses on keyword search, video result harvesting, and CSV export. This file also implements logout, CLI session creation/check, and profile retrieval endpoints, which are account/session management behaviors not mentioned in the manifest’s stated user-facing purpose.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

This file contains natural-language comments and stderr messages entirely in Chinese, including operational notices the user may need to act on. Under the policy, forcing a specific language without opt-in is a locale/language policy concern because the skill does not indicate any user choice or documented region-specific justification here.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The runtime messages shown during credential migration are user-facing operational guidance, but they are hardcoded in Chinese only. This can violate the language/locale policy when users are not given an option to select language or informed that the skill is region/language-specific.

Content

No source excerpt is available for this finding.