Back to skill

Security audit

微信公众号自动排版发布---一键安装

Security checks for vulnerabilities and agentic risk

Overview

This WeChat publishing skill is mostly purpose-built, but it needs review because it stores publishing credentials locally and has implementation flaws that could use the wrong account credentials or run unsafe shell commands during setup.

Review before installing. Use dedicated, low-privilege WeChat credentials, rotate them if they were already stored, check the actual WECHAT_ENV_FILE used by the script, and avoid running setup with untrusted environment variables. Treat publication commands as account-impacting actions and confirm the target account before creating drafts or publishing.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/setup.cjs:13
Finding

Shell Command Injection Through Environment-Controlled Workspace Path

Content
View full analysis

Vulnerability Details

File Location: scripts/setup.cjs:13, 23-25, 77-84
Vulnerability Type: OS command injection through shell-based argument concatenation
Risk Level: High

Vulnerable Code

js
const OPENCLAW_DIR = process.env.OPENCLAW_HOME || path.join(os.homedir(), '.openclaw');
js
function runCommand(args) {
  try {
    return { code: 0, output: execSync(args.join(' '), { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], shell: true }) };
  } catch (e) {
    return { code: e.status || 1, output: e.stderr || e.stdout || e.message };
  }
}
js
const { code, output } = runCommand([
  'openclaw', 'agents', 'add', agent.id,
  '--name', `"${agent.name}"`,
  '--workspace', `"${path.join(TEAM_DIR, agent.id)}"`,
  '--description', `"${agent.desc}"`,
]);

Technical Analysis

OPENCLAW_HOME is read from the process environment and incorporated into the workspace argument passed to runCommand. The function joins all arguments into one string and executes that string with shell: true.

Although the generated workspace path is surrounded by double quotes, shell metacharacters that remain active inside double quotes—particularly command substitutions such as $(command) and backticks—can still be evaluated by the shell. Consequently, quoting the value this way does not provide a security boundary.

The vulnerability is reachable during agent registration because the environment-derived path is included in the command passed to execSync.

Attack Path

  1. An attacker obtains the ability to influence the environment used to launch setup.cjs, such as through a wrapper script, CI configuration, compromised shell profile, or manipulated deployment command.
  2. The attacker sets OPENCLAW_HOME to a value containing shell command substitution, for example a path containing $(malicious-command).
  3. The setup script constructs the agent registration argumen ...[truncated 960 chars]
Remediation
View remediation

Remediation Suggestions

  • Replace shell-based string execution with an API that passes arguments directly to the executable:

    js
    const { execFileSync } = require('child_process');
    
    function runOpenClaw(args) {
      try {
        return {
          code: 0,
          output: execFileSync('openclaw', args, {
            encoding: 'utf-8',
            stdio: ['pipe', 'pipe', 'pipe'],
            shell: false,
          }),
        };
      } catch (e) {
        return {
          code: e.status || 1,
          output: e.stderr || e.stdout || e.message,
        };
      }
    }
    
  • Pass values such as names, descriptions, and workspace paths as individual arguments without adding shell quotes.

  • Avoid generic command helpers that accept preassembled command strings.

  • Validate OPENCLAW_HOME as an absolute filesystem path and reject null bytes or other invalid path content as defense in depth.

  • When possible, resolve the path with path.resolve and verify that the resulting directory has the expected owner and location.

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/wechat_publish.cjs:34
Finding

Cross-Workspace Credential Confusion and Insecure Access-Token Cache Permissions

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:41-47, scripts/wechat_publish.cjs:34-43, 177-213, templates/shulan/TOOLS.md:9
Vulnerability Type: Credential path inconsistency and insufficient protection of cached authentication tokens
Risk Level: Medium

Vulnerable Code

The installation instructions provision credentials in the publisher workspace:

bash
mkdir -p ~/.openclaw/workspace-wechat-publisher
cat > ~/.openclaw/workspace-wechat-publisher/.env << 'EOF'
WECHAT_APP_ID=User-provided AppID
WECHAT_APP_SECRET=User-provided AppSecret
WECHAT_API_BASE=https://api.weixin.qq.com
WECHAT_ACCOUNT_TYPE=User-selected account type
EOF
chmod 600 ~/.openclaw/workspace-wechat-publisher/.env 2>/dev/null || true

The agent template also declares that location:

md
The `wechat_publish.cjs` script calls the official WeChat API, and its configuration file is located at `~/.openclaw/workspace-wechat-publisher/.env`.

However, the executable uses an unrelated workspace:

js
function defaultEnvPath() {
  return path.join(os.homedir(), '.openclaw', 'workspace-content-team', '.env');
}

function defaultTokenCachePath() {
  return path.join(os.homedir(), '.openclaw', 'workspace-content-team', '.access_token');
}

const ENV_FILE = process.env.WECHAT_ENV_FILE || defaultEnvPath();
const TOKEN_CACHE = defaultTokenCachePath();

The token is then written without an explicit restrictive mode:

js
const cacheDir = path.dirname(TOKEN_CACHE);
fs.mkdirSync(cacheDir, { recursive: true });
fs.writeFileSync(TOKEN_CACHE, `${Math.floor(Date.now() / 1000)}\n${token}\n`, 'utf-8');

Technical Analysis

The declared configuration path and implemented configuration path do not match. The Skill instructs users to store credentials under workspace-wechat-publisher, while the executable defaults to reading credentials from workspace-content-team. The access-token cache is al ...[truncated 2424 chars]

Remediation
View remediation

Remediation Suggestions

  • Use the publisher workspace consistently for both credentials and tokens:

    js
    function publisherWorkspace() {
      return path.join(os.homedir(), '.openclaw', 'workspace-wechat-publisher');
    }
    
    const ENV_FILE =
      process.env.WECHAT_ENV_FILE ||
      path.join(publisherWorkspace(), '.env');
    
    const TOKEN_CACHE =
      process.env.WECHAT_TOKEN_CACHE ||
      path.join(publisherWorkspace(), '.access_token');
    
  • Create sensitive files with restrictive permissions atomically:

    js
    fs.writeFileSync(
      TOKEN_CACHE,
      `${Math.floor(Date.now() / 1000)}\n${token}\n`,
      { encoding: 'utf-8', mode: 0o600 }
    );
    fs.chmodSync(TOKEN_CACHE, 0o600);
    
  • Apply mode 0700 to the credential directory where supported.

  • Verify the owner and permissions of existing credential and token files before reading them.

  • Do not silently suppress permission-setting failures. Stop setup and report a clear error if secure permissions cannot be established.

  • Ensure WECHAT_ENV_FILE overrides are explicit and visible in status output without printing credential contents.

  • Keep credentials and token caches scoped to the same declared OpenClaw workspace to prevent cross-team account confusion.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/wechat_publish.cjs:220
Finding

WeChat Access-Token Prefix Disclosed in Command Output

Content
View full analysis

Vulnerability Details

File Location: scripts/wechat_publish.cjs:220-225
Vulnerability Type: Sensitive authentication data exposure through logs
Risk Level: Low

Vulnerable Code

js
async function cmdToken() {
  const token = await getAccessToken();
  console.log('✅ access_token obtained successfully and cached');
  console.log(`   Token: ${token.slice(0, 20)}...`);
}

Technical Analysis

The token command prints the first 20 characters of the WeChat access token. Although this is not the complete credential, authentication tokens should be treated as indivisible secrets and no portion should be written to routine output.

Command output may be retained in terminal logs, OpenClaw transcripts, CI logs, monitoring systems, debugging captures, or support bundles. Partial disclosure reduces the secrecy of the credential and creates avoidable sensitive-data exposure without providing operational value.

Attack Path

  1. A user or automated agent invokes node wechat_publish.cjs token.
  2. The script obtains or loads a valid access token.
  3. The first 20 characters are written to standard output.
  4. The output is captured by terminal logging, an agent transcript, CI infrastructure, or another log collector.
  5. A party with access to those logs obtains part of the authentication token.

No direct use of the partial token alone is demonstrated. The practical risk is increased when combined with another disclosure, predictable token structure, accidental output of the remaining token, or diagnostic artifacts containing adjacent secret material.

Impact Assessment

The immediate exposure is limited to a token prefix rather than the complete access token, so direct API impersonation is not established from this issue alone. Nevertheless, it unnecessarily exposes authentication material to every system and user able to read process output or retained logs.

If combined with another partial ...[truncated 176 chars]

Remediation
View remediation

Remediation Suggestions

  • Never print any part of an access token, AppSecret, or other authentication credential.

  • Replace the output with a non-sensitive success message:

    js
    async function cmdToken() {
      await getAccessToken();
      console.log('Access token obtained successfully and cached securely.');
    }
    
  • Review error handling and diagnostic logging to ensure complete tokens cannot appear in URLs, response dumps, exceptions, or debug output.

  • Configure log redaction as defense in depth for values matching known credential fields.

  • Limit access to historical agent transcripts and CI logs that may already contain token prefixes.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (19)

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The skill instructs the agent to write WeChat AppID and AppSecret into a plaintext .env file in the user's home directory. Persisting API credentials in a predictable local path creates a strong credential exposure risk through other tools, backups, shell access, or later compromise of the host.

Content

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

将凭证写入安全配置文件:

bash
mkdir -p ~/.openclaw/workspace-wechat-publisher
cat > ~/.openclaw/workspace-wechat-publisher/.env << 'EOF'
WECHAT_APP_ID=用户输入的AppID
WECHAT_APP_SECRET=用户输入的AppSecret
WECHAT_API_BASE=https://api.weixin.qq.com

Credential Access

High
Category
Privilege Escalation
Confidence
96% confidence
Finding

The file permission change confirms that a secret-bearing .env file is intentionally persisted on disk. Even with mode 600, the credential remains accessible to the current user account and to any process or malware running as that user, so compromise of the account exposes the WeChat publishing credentials.

Content

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

WECHAT_API_BASE=https://api.weixin.qq.com WECHAT_ACCOUNT_TYPE=用户选择的账号类型 EOF chmod 600 ~/.openclaw/workspace-wechat-publisher/.env 2>/dev/null || true

text

验证连通性:

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/wechat_publish.cjs (reported line 35)May include surrounding context.

js
const API_BASE = 'https://api.weixin.qq.com';

function defaultEnvPath() {
  return path.join(os.homedir(), '.openclaw', 'workspace-content-team', '.env');
}

function defaultTokenCachePath() {

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill performs sensitive operations involving environment-backed secrets and local credential persistence, but it declares no explicit tool scope or permissions boundary. This increases the chance that an agent executing the skill will access filesystem or environment capabilities without clear user visibility or policy enforcement.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The instructions ask the user for AppSecret and persist it locally, but they do not clearly warn that this is a sensitive credential, where it will be stored, who can access it, or what risks local storage creates. Users may disclose production secrets without informed consent, leading to credential leakage or later misuse if the workstation is compromised.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
94% confidence
Finding

The skill explicitly creates a persistent workspace and stores credentials there across sessions, which extends the lifetime of sensitive access beyond the immediate setup flow. Longer-lived secrets increase the attack window and make accidental reuse, exfiltration, or exposure through future agent actions more likely.

Content

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

将凭证写入安全配置文件:

bash
mkdir -p ~/.openclaw/workspace-wechat-publisher
cat > ~/.openclaw/workspace-wechat-publisher/.env << 'EOF'
WECHAT_APP_ID=用户输入的AppID
WECHAT_APP_SECRET=用户输入的AppSecret

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

WECHAT_API_BASE=https://api.weixin.qq.com WECHAT_ACCOUNT_TYPE=用户选择的账号类型 EOF chmod 600 ~/.openclaw/workspace-wechat-publisher/.env 2>/dev/null || true

text

验证连通性:

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The code executes local shell commands via execSync with shell enabled to check for OpenClaw and manage agent registration. Spawning shell commands and probing local installation state is not an obvious requirement of a skill described primarily as WeChat cover design, formatting, API publishing, and analytics unless the manifest explicitly frames it as a deployment installer.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The manifest describes a WeChat publishing agent team with design, formatting, API publishing, and analytics functions. This script's actual behavior is to create directories under the user's OpenClaw home, copy agent/template files, and register new agents with the OpenClaw CLI, which is deployment and local system configuration behavior rather than the publishing operations described in the manifest itself.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The script writes directories and copies files into the user's persistent OpenClaw workspace immediately, without an explicit consent step or a preview of what will be changed. In an adversarial skill ecosystem, silent filesystem modification increases the risk of unwanted agent installation, persistence, and trust confusion, especially because the copied files may later influence agent behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The script persists the WeChat access token to a predictable file under the user's home directory without setting restrictive file permissions or clearly warning the user that a reusable credential is being stored on disk. If another local user, process, backup system, or malware can read that file, the token can be reused to access the associated WeChat publishing APIs until it expires.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill explicitly instructs the agent to persist conversation-derived design tasks, review feedback, and brand preferences into memory files without any notice, consent flow, retention limit, or data minimization guidance. This creates a privacy and data-governance risk because user-supplied content, potentially including confidential campaign plans or sensitive business information, may be stored long-term and reused outside the user's 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 markdown file contains user-facing natural language exclusively in Chinese, including the title and all section text. 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.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · templates/shulan/TOOLS.md (reported line 4)May include surrounding context.

md
# 可用工具与环境配置

## 通用工具
- 文件读写:Read / Write / Edit(读取和编辑 workspace 内的文件)
- 网络搜索:Web Search(搜索行业数据、运营方法论)

## 微信公众平台 API 工具(核心)

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · templates/shulan/TOOLS.md (reported line 4)May include surrounding context.

md
# 可用工具与环境配置

## 通用工具
- 文件读写:Read / Write / Edit(读取和编辑 workspace 内的文件)
- 网络搜索:Web Search(搜索行业数据、运营方法论)

## 微信公众平台 API 工具(核心)

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
80% confidence
Finding

The header comments and user-facing console output consistently frame the skill as a WeChat publishing tool in Chinese, and the agent metadata is also Chinese-only. Under the stated policy, forcing a specific language or locale without opt-in can be a policy violation unless the constraint is explicitly documented and justified as region-specific.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

All natural-language instructions, usage strings, and operational messaging are presented only in Chinese, which effectively forces a specific language for users. The file does not offer an opt-in language choice or explain that the tool is intentionally limited to a Chinese-speaking or region-specific audience.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
77% confidence
Finding

The entire operating manual is presented only in Chinese and does not indicate that the language is optional, user-selected, or required for a region-specific purpose. Under the policy, forcing a specific language without opt-in can be a natural-language policy issue.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This file presents the skill name, role, and description exclusively in Chinese, which can amount to a language-policy issue if users are not given a language or locale choice. There is no accompanying note that the skill is intended only for a Chinese-language or region-specific context.

Content

No source excerpt is available for this finding.