Back to skill

Security audit

leesen86-news

Security checks for vulnerabilities and agentic risk

Overview

The documented news-fetching skill is mostly coherent, but the package also ships under-disclosed scripts that can send Feishu messages through a hardcoded local gateway credential.

Review this package before installing. Using new.js as documented should fetch BlockBeats news and print JSON, but the package also contains scripts that can send messages to Feishu through a local OpenClaw gateway using a credential embedded in the source. Do not run push-news.js or send-feishu.js unless you intentionally want that behavior, have rotated/replaced the exposed token, and have confirmed the target recipient and gateway permissions. The publisher should remove or fully document the messaging scripts, move credentials to secure configuration, fix the shell execution bug, and remove or update the unused ws dependency.

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
push-news.js:44
Finding

OS Command Injection Through the Keyword Argument

Content
View full analysis

Vulnerability Details

File Location: push-news.js:38-49, with attacker-controlled input originating at push-news.js:155-160
Vulnerability Type: OS command injection
Risk Level: High

Vulnerable code:

javascript
function fetchNewsRaw(keyword = 'openclaw', count = 5, maxChars = 500) {
  const scriptPath = path.join(__dirname, 'new.js');
  try {
    const result = execSync(`node "${scriptPath}" "${keyword}" ${count} ${maxChars}`, {
      encoding: 'utf-8',
      timeout: 30000
    });
    return result.trim();
  } catch (error) {
    console.error('获取资讯失败:', error.message);
    return null;
  }
}

Input source:

javascript
async function main() {
  const keyword = process.argv[2] || 'openclaw';
  const count = parseInt(process.argv[3]) || 5;
  const maxChars = parseInt(process.argv[4]) || 500;
  const target = process.argv[5] || DEFAULT_TARGET;

  console.log(`[${new Date().toISOString()}] 开始获取 ${keyword} 资讯...`);

  const rawNews = fetchNewsRaw(keyword, count, maxChars);

Technical Analysis

The keyword value is taken directly from process.argv[2] and interpolated into a command string passed to child_process.execSync. Because execSync executes the string through a shell, shell syntax embedded in the keyword is interpreted before Node.js invokes new.js.

Wrapping the value in double quotes is insufficient. Shell constructs such as command substitution remain active inside double quotes, and an embedded quote can terminate the intended argument and introduce additional commands. The code performs no shell escaping, allowlist validation, or argument separation.

The timeout only limits execution duration and does not prevent injected commands from reading files, modifying data, accessing credentials, or starting background processes.

Attack Path

  1. An attacker obtains the ability to invoke push-news.js or influence its keyword argument ...[truncated 1155 chars]
Remediation
View remediation

Remediation Suggestions

Replace shell-based execution with an API that passes arguments as a discrete array:

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

const result = execFileSync(
  process.execPath,
  [scriptPath, keyword, String(count), String(maxChars)],
  {
    encoding: 'utf-8',
    timeout: 30000,
    shell: false
  }
);

Prefer importing and calling the news-fetching functionality directly rather than starting another process. Export the necessary functions from new.js and keep command-line handling in a separate entry point.

In addition:

  • Validate keyword length and permitted characters according to business requirements.
  • Apply strict upper bounds to count and maxChars.
  • Run the Skill under a dedicated, unprivileged operating-system account.
  • Provide only the minimum required environment variables and filesystem permissions.
  • Add automated tests containing shell metacharacters, quotes, command substitutions, and newline characters to ensure they are treated strictly as data.

T09 · Insecure Skill Coding Practices

Error
Location
push-news.js:6
Finding

Hardcoded OpenClaw Gateway Bearer Credential and Feishu Routing Identifiers

Content
View full analysis

Vulnerability Details

File Location: push-news.js:6-9, 123-138; send-feishu.js:4-7, 9-24
Vulnerability Type: Hardcoded credential and deployment-specific identifiers
Risk Level: High

Vulnerable code in push-news.js:

javascript
const GATEWAY_URL = 'http://127.0.0.1:18789';
const GATEWAY_TOKEN = '30176f5d9e3d3372a70cefc8c1cf34248e5abc5888ec5519';
const ACCOUNT_ID = 'erbai';
const DEFAULT_TARGET = 'ou_56cdb528c6356bf5e344d2da35e98dad';
javascript
async function sendMessage(message, target = DEFAULT_TARGET) {
  const response = await fetch(`${GATEWAY_URL}/tools/invoke`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${GATEWAY_TOKEN}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      tool: 'message',
      args: {
        action: 'send',
        channel: 'feishu',
        accountId: ACCOUNT_ID,
        target: target,
        message: message
      }
    })
  });

Vulnerable code in send-feishu.js:

javascript
const GATEWAY_URL = 'http://127.0.0.1:18789';
const GATEWAY_TOKEN = '30176f5d9e3d3372a70cefc8c1cf34248e5abc5888ec5519';
const ACCOUNT_ID = 'erbai';
const DEFAULT_TARGET = 'ou_56cdb528c6356bf5e344d2da35e98dad';
javascript
async function sendMessage(message, target = DEFAULT_TARGET) {
  const response = await fetch(`${GATEWAY_URL}/tools/invoke`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${GATEWAY_TOKEN}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      tool: 'message',
      args: {
        action: 'send',
        channel: 'feishu',
        accountId: ACCOUNT_ID,
        target: target,
        message: message
      }
    })
  });

Technical Analysis

Both scripts embed the same bearer token directly in source code and transmit it in the HTTP Authorization header to the ...[truncated 2610 chars]

Remediation
View remediation

Remediation Suggestions

  • Immediately revoke and rotate the exposed gateway token if it has ever been active.
  • Remove the token, account ID, and default recipient from source code and repository history.
  • Load credentials from a protected secret manager or environment variable at runtime.
  • Require the destination to be explicitly configured rather than shipping a deployment-specific default.
  • Fail safely when required configuration is absent; do not fall back to a shared credential or recipient.
  • Issue a narrowly scoped token that permits only the necessary message operation, account, channel, and approved destinations.
  • Separate the core news-fetching Skill from the optional notification integration so users do not grant messaging capability when they only need structured news output.
  • Restrict gateway access to the intended process or operating-system identity. Do not expose the loopback service through container port mappings or reverse proxies.
  • Where supported, use a Unix-domain socket with filesystem permissions or authenticated HTTPS rather than plaintext local HTTP.
  • Prevent credentials from appearing in logs, exceptions, process arguments, test fixtures, and generated artifacts.
  • Add automated secret scanning and pre-commit checks to prevent future bearer tokens from being committed.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

声明描述的是一个“抓取与筛选并输出 JSON”的数据处理技能,重点在于拉取 BlockBeats 数据、关键词筛选、清洗 HTML 和格式化时间后返回 JSON。实际代码的核心目的则是“自动推送资讯”:它通过 execSync 调用 new.js 获取数据后,进行去重、格式化成人类可读的快报文本,并调用本地消息网关向飞书发送消息,还会读写 .sent-news.json 记录已推送项目。这里最关键的未声明能力是外发消息和持久化缓存;同时实际输出不是 JSON,而是面向飞书的文本/Markdown消息。因此描述与行为存在明显且实质性的偏差。

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

声明描述的是一个资讯抓取与筛选技能,核心能力应包括访问 BlockBeats 数据源、提取/清洗内容、关键词过滤、格式化输出 JSON。但实际代码完全没有任何抓取 BlockBeats、解析 HTML、筛选资讯或格式化时间的实现。相反,它硬编码了 Gateway 地址、认证 token、账户 ID 和默认飞书接收方,并执行消息发送。这属于与声明用途 materially different 的主要功能,且访问的资源(本地消息网关/飞书)与声明中的 BlockBeats 数据源明显不一致,因此应判定为描述与行为严重不匹配。

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
98% confidence
Finding

The lockfile pins ws to version 8.19.0, and the supplied advisory data indicates this exact version is affected by an uninitialized memory disclosure and a memory-exhaustion denial-of-service issue. Because this skill fetches external data and may operate in networked or automation contexts, a vulnerable WebSocket library increases exposure to remotely triggered information leakage or service disruption.

Content

No source excerpt is available for this finding.

Known Vulnerable Dependency: ws==8.19.0 — 2 advisory(ies): CVE-2026-45736 (ws: Uninitialized memory disclosure); CVE-2026-48779 (ws: Memory exhaustion DoS from tiny fragments and data chunks)

High
Category
Supply Chain
Confidence
98% confidence
Finding

The package depends on ws 8.19.0, which the finding indicates is affected by an uninitialized memory disclosure and a memory-exhaustion denial of service. If this skill or any surrounding runtime exposes WebSocket functionality directly or indirectly, an attacker could potentially crash the process or access unintended memory contents, making this significantly more dangerous than a generic dependency hygiene issue.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill manifest says the capability is to fetch and filter crypto news and output cleaned JSON, but this code instead sends data to an external Feishu messaging gateway using a hardcoded bearer token. That is a material capability expansion because it can exfiltrate content or perform side effects outside the declared scope, and users invoking a data-processing skill would not reasonably expect outbound message delivery.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

Outbound Feishu messaging is not justified by the stated purpose of pulling and filtering news, yet the script invokes an HTTP gateway and sends messages to a default target. In context, this makes the skill more dangerous because the declared task is passive data retrieval, but the implementation performs autonomous external communication with a hardcoded destination and credential.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The file's behavior does not match the declared skill purpose of fetching and filtering crypto news; instead, it implements outbound Feishu messaging. Capability mismatch is a strong indicator of hidden functionality, and in an agent skill this can be abused for covert notification, data exfiltration, or unauthorized actions under a misleading description.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

This skill includes an outbound messaging path that is not justified by the advertised crypto-news use case. In context, unjustified communication features materially increase risk because they can transmit agent-controlled content to external recipients, enabling exfiltration, spam, or covert signaling without aligning to expected functionality.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill clearly documents outbound network access to a third-party API, but it does not declare any explicit tool scope such as permissions or allowed-tools. In an agent environment, missing scope declarations weaken governance and make it harder for operators to understand or constrain what the skill is permitted to do.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file’s natural-language instructions and usage guidance are presented only in Chinese, which can force a specific language on users without an explicit choice. The policy allows locale constraints only when justified or when users are given an opt-in/choice, neither of which is present here.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
83% confidence
Finding

The skill performs external network transmission to a third-party API, which creates normal but real data egress and supply-chain trust considerations. In this context the behavior is aligned with the skill's stated purpose, so the danger is limited, but unreviewed outbound connectivity can still leak query terms, timing, and requester metadata.

Content

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

md
## 能力概览

- 🔄 **并发抓取**:从 `https://api.theblockbeats.news/v1/open-api/open-flash` 分页抓取最新快讯
- 🔍 **关键词筛选**:对标题与内容做不区分大小写的关键词匹配(支持多个关键词)
- 🧹 **内容清洗**:自动移除 `content` 等字段中的 HTML 标签,只保留纯文本
- ⏱ **时间格式化**:将 `create_time` 等 Unix 秒时间戳转换为 `YYYY-MM-DD HH:mm:ss`,并保留原始值

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 · new.js (reported line 17)May include surrounding context.

js
* - 如果 keyword 不为空:先在最多 maxLimit 条内做关键词匹配,再返回前 limit 条匹配结果
 */

const BASE_URL = 'https://api.theblockbeats.news/v1/open-api/open-flash';
const PAGE_SIZE = 200;

/**

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code reformats fetched items into a bulletin string rather than returning the manifest-promised JSON. While not a direct exploit primitive by itself, it is a scope/deception issue that can break downstream automation, conceal data provenance, and mask the fact that the skill behavior differs from what users were told to expect.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script automatically sends an HTTP request that triggers message delivery with no interactive confirmation, only console progress logs. This creates a silent side-effect risk: a user may believe they are merely fetching news, while the code actually publishes content to an external channel immediately.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

A hardcoded bearer token is embedded directly in the source and used to authorize requests to a gateway. Secrets in code are easily leaked through source distribution, logs, backups, or repository exposure, after which an attacker could reuse the token to invoke the messaging gateway.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script accepts arbitrary message content and sends it over HTTP to a local gateway for onward delivery to Feishu, with no user-facing disclosure or approval. In a mislabeled skill, silent outbound transmission is especially risky because users expecting local news processing may unknowingly allow external delivery of sensitive prompts, data, or generated content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

This markdown file describes a skill that calls an external API, which can affect privacy/system behavior by sending network requests outside the local environment. While the behavior is explained functionally, there is no explicit user warning or disclosure about contacting a third-party endpoint when the skill is run.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
96% confidence
Finding

The request hard-codes lang=cn, which enforces a specific locale for all users. This is a natural-language policy concern because the skill does not offer an opt-in, override, or explanation that the tool is intentionally region-specific.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
92% confidence
Finding

The dependency is specified with a caret range (^8.19.0), which allows automatic installation of future 8.x releases instead of a fully fixed version. This weakens build reproducibility and can unexpectedly pull in vulnerable or behavior-changing releases, which is a real supply-chain risk even though it is lower severity on its own.

Content

Scanner excerpt · package.json (reported line 3)May include surrounding context.

json
{
  "dependencies": {
    "ws": "^8.19.0"
  }
}

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The script persists delivery history to a local file without clearly warning the user that execution creates local state. This is lower severity than the outbound messaging issue, but it can still affect privacy, reproducibility, and operator expectations, especially in automation environments where stateless behavior is assumed.

Content

No source excerpt is available for this finding.