Back to skill

Security audit

myskill

Security checks for vulnerabilities and agentic risk

Overview

This skill mostly fetches public Douyin trends, but it needs Review because bundled automation can write files, run shell commands with unvalidated input, and prepare Telegram messages for a fixed recipient.

Review this before installing if you plan to run the cron/helper scripts or connect outputs to a messaging tool. Use the basic douyin.js fetch path only if you just need public trend data, and avoid running get-hot-trend.js with untrusted arguments. Do not let downstream automation consume the included Telegram chat_id unless that recipient is intentionally yours.

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
scripts/get-hot-trend.js:13
Finding

OS Command Injection Through an Unvalidated Command-Line Argument

Content
View full analysis

Vulnerability Details

File Location: scripts/get-hot-trend.js, lines 13-18 and line 73
Vulnerability Type: OS command injection
Risk Level: High

Vulnerable Code

javascript
function getHotTrend(limit = 10) {
  try {
    const scriptPath = path.join(__dirname, 'douyin.js');
    const output = execSync(`node "${scriptPath}" hot ${limit}`, {
      encoding: 'utf-8',
      cwd: path.dirname(scriptPath)
    });

The attacker-controlled value originates here:

javascript
const limit = process.argv[2] || 10;

Technical Analysis

The limit value is read directly from process.argv[2] without type validation or range enforcement. It is then interpolated into a string passed to child_process.execSync.

execSync executes its string through a system shell. Consequently, shell metacharacters contained in limit, such as semicolons, command substitutions, redirections, or pipes, are interpreted as shell syntax rather than as a numeric argument to douyin.js.

Although the intended value is a count, the application does not ensure that it is an integer. Quoting scriptPath does not protect the separately interpolated limit value.

Attack Path

  1. An attacker obtains the ability to invoke scripts/get-hot-trend.js or influence the argument supplied by an automation or cron integration.

  2. The attacker supplies a crafted value instead of a numeric limit. For example:

    bash
    node scripts/get-hot-trend.js '10; touch /tmp/clawhub-command-injection #'
    
  3. The value is assigned to limit without validation.

  4. The generated shell command becomes equivalent to:

    bash
    node "/project/scripts/douyin.js" hot 10; touch /tmp/clawhub-command-injection #
    
  5. The shell executes both the intended Node.js script and the injected command.

More damaging payloads could read accessible files, modify project data, invoke network utilities, or ex ...[truncated 849 chars]

Remediation
View remediation

Remediation Suggestions

Avoid invoking a shell. Use execFileSync or spawnSync with a discrete argument array:

javascript
const { execFileSync } = require('child_process');

function getHotTrend(limit = 10) {
  const parsedLimit = Number(limit);

  if (!Number.isInteger(parsedLimit) || parsedLimit < 1 || parsedLimit > 50) {
    throw new TypeError('The limit must be an integer between 1 and 50.');
  }

  const scriptPath = path.join(__dirname, 'douyin.js');
  return execFileSync(
    process.execPath,
    [scriptPath, 'hot', String(parsedLimit)],
    {
      encoding: 'utf-8',
      cwd: path.dirname(scriptPath),
      timeout: 15000
    }
  );
}

Additional hardening measures:

  • Validate the argument before it reaches any process-execution function.
  • Enforce a conservative numeric range to prevent resource abuse.
  • Use process.execPath rather than relying on shell resolution of node.
  • Run the skill under a dedicated, least-privileged account.
  • Add automated tests containing shell metacharacters and verify that they are rejected.

T09 · Insecure Skill Coding Practices

Warning
Location
cron-job.js:139
Finding

Hard-Coded Telegram Recipient Can Cause Unintended Message Routing

Content
View full analysis

Vulnerability Details

File Location: cron-job.js, lines 139-147
Vulnerability Type: Hard-coded external recipient identifier
Risk Level: Medium

Vulnerable Code

javascript
const jsonOutput = {
  success: true,
  timestamp: new Date().toISOString(),
  timezone: 'Asia/Shanghai',
  chat_id: '8428610733',
  channel: 'telegram',
  message: message,
  items: items.slice(0, limit),
  format: 'markdown'
};

The routing object is subsequently persisted for use by the surrounding integration:

javascript
const jsonFile = path.join(__dirname, 'daily-hot-trend-output.json');
fs.writeFileSync(jsonFile, JSON.stringify(jsonOutput, null, 2), 'utf-8');

Technical Analysis

The Telegram chat_id is embedded directly in executable project code rather than being supplied through explicit deployment configuration. The script describes the generated JSON as output for the OpenClaw messaging tool, meaning a downstream automation that trusts this routing metadata may send the generated message to this fixed account.

The identifier is also duplicated in the committed daily-hot-trend-output.json artifact. It is not an authentication secret by itself, but it is destination metadata that controls where downstream messages may be delivered.

The reviewed script only prepares and writes the message object; it does not directly call the Telegram API. Therefore, actual disclosure depends on a downstream OpenClaw or messaging integration consuming the generated object. Nevertheless, the fixed destination creates an unsafe default and can route information without the deploying user's explicit recipient selection.

Attack Path

  1. A user installs or schedules the skill expecting trend output to be sent to a recipient configured in their own environment.
  2. cron-job.js ignores deployment-specific recipient configuration and creates output containing the fixed chat_id.
  3. The output is wri ...[truncated 1254 chars]
Remediation
View remediation

Remediation Suggestions

Remove the fixed recipient from source code and require an explicit deployment setting:

javascript
const chatId = process.env.TELEGRAM_CHAT_ID;

if (!chatId || !/^-?\d+$/.test(chatId)) {
  throw new Error('TELEGRAM_CHAT_ID must be explicitly configured.');
}

const jsonOutput = {
  success: true,
  timestamp: new Date().toISOString(),
  timezone: 'Asia/Shanghai',
  chat_id: chatId,
  channel: 'telegram',
  message,
  items: items.slice(0, limit),
  format: 'markdown'
};

Additional hardening measures:

  • Require explicit recipient configuration rather than providing an external default.
  • Display the selected destination and obtain user confirmation during setup.
  • Maintain an allowlist when the deployment supports only approved recipients.
  • Do not commit generated output files containing user-specific routing metadata.
  • Document that running the integration may cause an external message to be sent.
  • Keep bot tokens and other messaging credentials in a secret manager or protected environment variables.
Vulnerability Patterns
  • 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
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (24)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Undisclosed local file writes can create security and privacy risk in an agent environment because they persist fetched data outside the expected response channel, potentially exposing information to other processes, users, or later tasks. In a skill whose declared role is simple data retrieval, hidden persistence materially changes the trust boundary and can enable unintended data retention or abuse, even if the fetched data is public.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

Undisclosed local file writes can create security and privacy risk in an agent environment because they persist fetched data outside the expected response channel, potentially exposing information to other processes, users, or later tasks. In a skill whose declared role is simple data retrieval, hidden persistence materially changes the trust boundary and can enable unintended data retention or abuse, even if the fetched data is public.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

Undisclosed local file writes can create security and privacy risk in an agent environment because they persist fetched data outside the expected response channel, potentially exposing information to other processes, users, or later tasks. In a skill whose declared role is simple data retrieval, hidden persistence materially changes the trust boundary and can enable unintended data retention or abuse, even if the fetched data is public.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Undisclosed local file writes can create security and privacy risk in an agent environment because they persist fetched data outside the expected response channel, potentially exposing information to other processes, users, or later tasks. In a skill whose declared role is simple data retrieval, hidden persistence materially changes the trust boundary and can enable unintended data retention or abuse, even if the fetched data is public.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/douyin.js hot

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
node scripts/douyin.js hot

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The header comment says '直接发送到 Telegram', which implies an actual outbound send operation. In this file, the code formats a message, writes local files, and prints output for another tool to capture, but no Telegram API call or send action occurs.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The message formatting logic is specifically tailored for Telegram Markdown output, including inline links and ranking presentation, despite the skill being described as a Douyin trend fetcher. This broadens the skill from data retrieval into platform-specific message preparation, which can enable covert repurposing for automated dissemination through external channels.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The timestamp formatting explicitly forces zh-CN and Asia/Shanghai, which is a natural-language/locale policy choice embedded in the code. The file does not provide any opt-in, configuration, or documented justification that this skill is intended only for Chinese-language or China-region users.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill prepares Telegram delivery artifacts including a hard-coded chat_id, channel metadata, and a formatted outbound message, which exceeds the stated purpose of merely retrieving Douyin hot-trend data. Even though this file does not directly send the message, it is clearly structured for downstream exfiltration or unsolicited outbound delivery through another component, creating a data-flow expansion beyond user expectations.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This plain-text skill output forces a specific language/locale for all users, which matches the policy-violation category for language constraints. There is no indication that the skill is region-specific, optional by user preference, or that alternative languages are supported.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The output embeds Telegram-specific delivery metadata such as chat_id and channel, which is unrelated to the stated purpose of returning Douyin hot-trend content. Exposing integration metadata increases unnecessary data disclosure and can leak internal routing or recipient identifiers to downstream consumers, logs, or users.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This JSON output contains a fully Chinese-language message body and pairs it with a fixed Asia/Shanghai timezone, but provides no indication that the language/locale was user-selected or that the skill is explicitly region-scoped. Under the policy, fixed language or locale behavior without opt-in or clear justification is a natural-language policy violation.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The HTTP request explicitly sets Accept-Language to prefer zh-CN, and the script's user-facing output and comments are also fixed in Chinese. The policy allows locale constraints only when the user is offered a choice or the limitation is clearly documented and justified, which is not present here.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The manifest says the skill returns Douyin hot-ranking data including title, heat value, jump link, and cover image across multiple content domains. This script only parses ranked titles and heat values into a message, stores that message and raw text locally, and never extracts or outputs links or cover images. That is a semantic mismatch between the declared skill output and this file's implemented behavior.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The JSON hard-codes the timezone to "Asia/Shanghai" and all user-facing content in message and rawData is presented in Chinese. For a general skill artifact, this is a natural-language locale policy issue because it imposes a specific language/locale without offering user choice or documenting that the skill is intentionally region-specific.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The line '每天下午6点自动推送' asserts scheduled automatic delivery behavior, but this file only contains a static rendered message and no implementation or metadata showing automation. This is an intent-level claim in the documentation/output text that goes beyond what the artifact itself demonstrates.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

The manifest says the skill outputs titles, heat values, jump links, and cover images where available, across multiple Douyin hot-list domains such as videos, challenges, and music. In this file, items 5-10 include only titles and heat values without links or cover images, and the output is limited to a single '抖音热榜 TOP 10' list rather than demonstrating multiple content domains.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
76% confidence
Finding

The package metadata is written to target Chinese-language Douyin content specifically, including a Chinese-only description and the locale keyword "chinese". There is no indication that this locale constraint is optional, user-selectable, or justified as a region-specific tool, which can conflict with language/locale choice policy.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
95% confidence
Finding

The request hard-codes Accept-Language: zh-CN,zh;q=0.9,en;q=0.8, which imposes a specific language/locale preference in outbound traffic. The file does not offer a user opt-in or configuration option, and no region-specific justification is documented in the script.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

The script invokes a shell command via execSync and interpolates the user-controlled limit argument directly into the command string. If an attacker can supply a crafted argument, this can lead to command injection and arbitrary command execution in the context of the skill runner.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script formats the update time using the hard-coded locale 'zh-CN' and timezone 'Asia/Shanghai'. This is a natural-language locale policy issue because the behavior is forced rather than user-selectable, and the file does not document a region-specific requirement that would justify the constraint.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The manifest describes fetching and outputting Douyin hot-list data, which implies retrieval and presentation. This file additionally persists results to local text and JSON files under the script directory, adding local write side effects not suggested by the description. While not highly sensitive, it exceeds the plain retrieval/output behavior users would infer from the manifest.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The file presents all user-facing content in Chinese, including headings and labels, with no indication that language selection is optional or region-specific. Under the policy, fixed language/locale behavior without user opt-in can be a natural-language policy concern.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
cron-job.js:16

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/get-hot-trend.js:16