Back to skill

Security audit

微信公众号发布技能

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its stated WeChat draft-publishing purpose, but it handles powerful account credentials and installation steps in ways users should review carefully before installing.

Install only if you are comfortable giving this skill WeChat official account draft-creation authority. Avoid entering AppSecret as a command-line argument, prefer a protected secret store or tightly permissioned local file, rotate the secret if it may have been exposed, and do not run the documented curl | sudo bash or sudo npm install steps without independent verification and version pinning.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T03 · Remote Payload Retrieval and Execution

Error
Location
docs/user_guide.md:82
Finding
Privileged Remote Script Download and Immediate Execution<![CDATA[ ## Vulnerability Details **File Location**: `docs/user_guide.md:82-90` **Vulnerability Type**: Remote payload retrieval and execution **Risk Level**: Critical ### Vulnerable Code ```bash # 1. Open a terminal # 2. Install Node.js (if not installed) curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - sudo apt-get install -y nodejs # 3. Install OpenClaw sudo npm install -g openclaw ``` ### Technical Analysis The installation guide pipes content retrieved from an external URL directly into a privileged shell. The retrieved script is not pinned by digest, saved for inspection, or verified using a cryptographic signature before execution. Although HTTPS protects the connection in transit under normal circumstances, it does not protect users if the upstream distribution service, account, DNS infrastructure, certificate authority, or hosted script is compromised. The effective code executed by this instruction can also change after the Skill package has been audited. Use of `sudo -E bash` executes the remote content as root while preserving parts of the caller's environment. This exceeds the minimum privileges needed merely to explain how to install a runtime and creates a direct root-level code-execution channel. ### Attack Path 1. An attacker compromises the remote setup-script host, its publishing credentials, or a relevant network trust dependency. 2. The attacker modifies the script returned from `https://deb.nodesource.com/setup_16.x`. 3. A user follows the documented installation procedure. 4. `curl` retrieves the attacker-controlled response. 5. The shell pipeline sends the response directly to `sudo -E bash` without local review or integrity validation. 6. The malicious commands execute with root privileges. 7. The payload can modify system files, steal credentials, install persistence, or compromise other accounts and applications on the host. ### Impact Assessment Successful exploitation provides arbitrary command execution ...[truncated 231 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the `curl | sudo bash` pipeline. 2. Prefer distribution-provided packages or manually documented repository configuration steps. 3. If an external installer is unavoidable: - Download it to a local file first. - Pin a specific immutable version. - Publish and verify a cryptographic checksum and vendor signature. - Display the expected signer identity and fingerprint. - Allow the user to inspect the script before execution. 4. Do not preserve unnecessary environment variables when invoking privileged commands. 5. Run only the specific repository-registration or package-installation operations requiring elevation. 6. Document a reproducible, versioned installation process whose effective payload cannot silently change after review. ]]>

T08 · Insecure Dependencies

Error
Location
docs/user_guide.md:82
Finding
Unpinned Global Package Installation with Elevated Privileges<![CDATA[ ## Vulnerability Details **File Location**: `docs/user_guide.md:82-93` and `docs/user_guide.md:429-437` **Vulnerability Type**: Insecure dependency installation **Risk Level**: High ### Vulnerable Code ```bash # 2. Install Node.js (if not installed) curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash - sudo apt-get install -y nodejs # 3. Install OpenClaw sudo npm install -g openclaw # 4. Verify installation openclaw --version ``` The troubleshooting section repeats the privileged global installation pattern: ```bash # Solution 1: Use the Taobao mirror npm config set registry https://registry.npmmirror.com npm install -g openclaw # Solution 2: Use sudo (macOS/Linux) sudo npm install -g openclaw ``` ### Technical Analysis The guide installs `openclaw` globally without pinning a reviewed version or validating package integrity. Package installation can execute lifecycle scripts, and an unpinned command resolves to whichever release and transitive dependencies are current at installation time. The risk is amplified when the command is run through `sudo`, because package lifecycle code may execute with elevated privileges. The alternative registry recommendation also changes the global npm registry configuration, extending trust to a different package source for subsequent npm operations. This creates a supply-chain exposure: a compromised package release, maintainer account, transitive dependency, or configured registry could introduce code that was not part of the audited Skill artifact. ### Attack Path 1. An attacker compromises the package publisher, a transitive dependency, or the configured package registry. 2. The attacker publishes a malicious package version or substitutes malicious package content. 3. Because no version is pinned, the documented command resolves to the malicious release. 4. npm downloads the package and its dependency tree. 5. Package lifecycle scripts execute during installation. 6. If the user follows th ...[truncated 582 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin `openclaw` to a specific audited version rather than installing the latest release. 2. Verify package integrity using an approved lockfile, registry integrity metadata, signatures, or published cryptographic hashes. 3. Avoid running npm as root. Use a user-scoped installation, a version manager, or an isolated environment. 4. Do not modify the user's global npm registry as a troubleshooting shortcut. If an alternate registry is required, scope it to the individual command and document its trust implications. 5. Disable package lifecycle scripts when they are unnecessary, or review all required lifecycle scripts before installation. 6. Document the expected package publisher, package source, version, and integrity value. 7. Regularly review and pin transitive dependencies through a reproducible installation mechanism. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
docs/user_guide.md:218
Finding
WeChat Secrets Exposed Through Command Arguments and Plaintext Files<![CDATA[ ## Vulnerability Details **File Location**: `docs/user_guide.md:218-238`; `scripts/publish.py:108-120`; `scripts/publish.py:169-176` **Vulnerability Type**: Insecure credential and token handling **Risk Level**: High ### Vulnerable Code The guide recommends supplying the AppSecret as a command-line argument: ```bash # Complete configuration with one command openclaw skill config wechat-publisher \ --app-id wxebff9eadface1489 \ --app-secret 44c10204ceb1bfb3f7ac096754976454 ``` It also recommends storing the AppSecret directly in a plaintext JSON file: ```bash # 1. Open the configuration file # Location: ~/.agents/skills/wechat-publisher/config/config.json # 2. Edit the file: { "app_id": "wxebff9eadface1489", "app_secret": "44c10204ceb1bfb3f7ac096754976454", "schedule": "06:00", "template": "v5-simple", "news_count": 15, "timezone": "Asia/Shanghai" } ``` The publishing script accepts the plaintext configuration value: ```python def _get_app_secret(self): """Get AppSecret from an environment variable or configuration.""" app_secret = os.environ.get("WECHAT_APP_SECRET") if app_secret: self.logger.info("AppSecret loaded from environment variable") return app_secret app_secret = self.config.get("app_secret") if app_secret: self.logger.info("AppSecret loaded from configuration file") return app_secret ``` The acquired access token is cached as plaintext without explicitly enforcing restrictive file permissions: ```python cache_data = { "token": token, "time": datetime.now().isoformat(), "expires_in": result.get("expires_in", 7200) } with open(self.token_cache_path, "w", encoding="utf-8") as f: json.dump(cache_data, f, indent=2, ensure_ascii=False) self.logger.info("Token cached") ``` ### Technical Analysis Supplying an AppSecret on the command line can expose it through shell history, command logging, terminal capture, automation logs, and process inspection. Stor ...[truncated 2145 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove all examples that place secrets in command-line arguments. 2. Collect secrets through hidden interactive input, standard input, or a platform-native secret manager. 3. Prefer an operating-system credential store or a dedicated secret-management service over plaintext JSON. 4. If file-based storage is unavoidable: - Create files atomically with mode `0600`. - Verify the file is owned by the expected user. - Reject symbolic links and unexpectedly permissive existing files. - Keep secrets outside the Skill's distributable source tree. 5. Protect `token-cache.json` with restrictive permissions and minimize token retention. 6. Avoid placing access tokens in URLs where possible. If the upstream API requires query parameters, ensure URLs and request metadata are never logged. 7. Redact AppSecrets and tokens from logs, errors, status files, command output, and diagnostic bundles. 8. Add credential-rotation instructions and require rotation after suspected disclosure. 9. Replace realistic-looking documentation values with unmistakably nonfunctional placeholders. ]]>
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
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (27)

Tainted flow: 'params' from os.environ.get (line 147, credential/environment) → requests.get (network output)

Critical
Category
Data Flow
Content
for i in range(1, retry_count + 1):
            try:
                self.logger.info(f"获取 Token(尝试 {i}/{retry_count})")
                response = requests.get(token_url, params=params, timeout=30)
                response.raise_for_status()
                result = response.json()
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'params' from os.environ.get (line 147, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
for i in range(1, retry_count + 1):
            try:
                self.logger.info(f"创建草稿(尝试 {i}/{retry_count})")
                response = requests.post(
                    draft_url,
                    params=params,
                    json=data,
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Chaining Abuse

High
Category
Tool Misuse
Content
```bash
# 1. 打开终端
# 2. 安装 Node.js(如未安装)
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs

# 3. 安装 OpenClaw
Confidence
97% confidence
Finding
The chained pattern "curl ... | sudo ... bash" combines network retrieval with immediate privileged execution, enabling one-step compromise if the fetched content is malicious or altered. This is especially dangerous in user-facing install docs because readers may execute it verbatim without understanding the trust boundary.

Missing User Warnings

High
Confidence
99% confidence
Finding
The guide instructs users to pass the AppSecret directly as a command-line argument, which commonly exposes credentials via shell history, process listings, audit logs, terminal recording, and support screenshots. For a publishing skill tied to a WeChat account, compromise of this secret can enable unauthorized API access and account abuse.

Missing User Warnings

High
Confidence
98% confidence
Finding
The guide tells users to store the AppSecret in a plaintext config file and does not prominently warn about access control, secret-at-rest protection, backup leakage, or accidental source-control inclusion. In the context of an automation skill, plaintext storage increases the chance that long-lived credentials are harvested from the filesystem, synced folders, or diagnostic bundles.

Natural-Language Policy Violations

Medium
Confidence
86% confidence
Finding
The configuration enforces a specific timezone, "Asia/Shanghai", with no indication of user opt-in or a justified region-specific requirement. The audit criteria require flagging locale policy issues when a skill forces a locale without offering a choice or documenting the constraint.

Natural-Language Policy Violations

Medium
Confidence
80% confidence
Finding
The document requires users to operate through a fully Chinese-language guide and repeatedly uses China-specific locale assumptions such as `Asia/Shanghai` and Beijing-time phrasing, but it does not present this as an opt-in regional edition or offer an alternative language/locale path. Under the stated policy, forcing a specific language or locale without user choice is a natural-language policy concern.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
```bash
# 1. 打开终端
# 2. 安装 Node.js(如未安装)
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs

# 3. 安装 OpenClaw
Confidence
92% confidence
Finding
The command pipes a remote script directly into a root shell via "curl ... | sudo -E bash -", which is a classic high-risk pattern because network compromise, mirror compromise, DNS/TLS interception, or content tampering can become immediate privileged code execution. In installation documentation, this is more dangerous than ordinary sudo use because it removes any review step before executing downloaded code as root.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
```bash
# 1. 打开终端
# 2. 安装 Node.js(如未安装)
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs

# 3. 安装 OpenClaw
Confidence
92% confidence
Finding
The command pipes a remote script directly into a root shell via "curl ... | sudo -E bash -", which is a classic high-risk pattern because network compromise, mirror compromise, DNS/TLS interception, or content tampering can become immediate privileged code execution. In installation documentation, this is more dangerous than ordinary sudo use because it removes any review step before executing downloaded code as root.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# 1. 打开终端
# 2. 安装 Node.js(如未安装)
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs

# 3. 安装 OpenClaw
sudo npm install -g openclaw
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
# 1. 打开终端
# 2. 安装 Node.js(如未安装)
curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
sudo apt-get install -y nodejs

# 3. 安装 OpenClaw
sudo npm install -g openclaw
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Intent-Code Divergence

Medium
Confidence
99% confidence
Finding
The guide includes a full example AppSecret immediately after stating that the secret is sensitive and only displayed once. Even if presented as an example, publishing realistic credential material normalizes unsafe handling and can lead users to copy secrets into screenshots, tickets, chats, or docs; if the example were ever real, it would be a direct credential exposure.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The configuration display example claims the AppSecret is masked but still reveals most of the value, which materially reduces secrecy and teaches an unsafe display pattern. Partial disclosure can aid shoulder-surfing, log leakage, screenshot compromise, or correlation with other exposed fragments.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
npm install -g openclaw

# 解决方案 2:使用 sudo(macOS/Linux)
sudo npm install -g openclaw
```

**Q2: openclaw 命令找不到?**
Confidence
70% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Content
```bash
# 检查配置文件权限
# macOS/Linux:
chmod 600 ~/.agents/skills/wechat-publisher/config/config.json

# Windows: 以管理员身份运行配置命令
```
Confidence
80% confidence
Finding
Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The script claims to be a publishing utility but also implements unrelated license enforcement and local usage metering. Hidden or undocumented control logic increases supply-chain risk because operators may grant the skill more trust than warranted, and the extra code path can deny service or alter behavior unexpectedly.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The top-level natural-language description is entirely in Chinese and presents the skill as a general-purpose publishing script, but it does not indicate that Chinese is optional or that the tool is restricted to a Chinese-language context. Under the stated policy, forcing a specific language without opt-in is a natural-language policy concern.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
The script reads sensitive credentials from environment variables or config and immediately uses them to call an external service without any explicit user-facing notice at runtime. In an agent-skill setting, this matters because users may trigger the skill without realizing it will consume locally available secrets and perform network actions on their behalf.

External Transmission

Medium
Category
Data Exfiltration
Content
# 获取新 Token
        app_secret = self._get_app_secret()
        token_url = "https://api.weixin.qq.com/cgi-bin/token"
        params = {
            "grant_type": "client_credential",
            "appid": self.config["app_id"],
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
# 获取新 Token
        app_secret = self._get_app_secret()
        token_url = "https://api.weixin.qq.com/cgi-bin/token"
        params = {
            "grant_type": "client_credential",
            "appid": self.config["app_id"],
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
The skill contains local license checks and trial tracking that are unrelated to the operational task of drafting WeChat posts. In a security review context, unnecessary gating logic is risky because it adds opaque behavior, local state manipulation, and execution control that users did not ask for.

External Transmission

Medium
Category
Data Exfiltration
Content
for i in range(1, retry_count + 1):
            try:
                self.logger.info(f"创建草稿(尝试 {i}/{retry_count})")
                response = requests.post(
                    draft_url,
                    params=params,
                    json=data,
Confidence
80% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The skill advertises automated collection, HTML generation, and scheduled publishing to a WeChat public account draft box, but it does not clearly warn users that generated content may be published automatically on a schedule. This can cause unintended posting, reputational harm, or policy violations if users do not understand the automation scope before configuring or enabling the skill.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
The skill requests sensitive platform credentials (`app_id` and especially `app_secret`) but provides no warning about how those secrets are stored, transmitted, or protected. In the context of a publishing skill tied to an official account, mishandling these credentials could enable unauthorized access, content publication, or takeover of associated API capabilities.

Vague Triggers

Low
Confidence
78% confidence
Finding
This manifest-style JSON file hard-codes the timezone to "Asia/Shanghai", which may act as an implicit locale constraint without clarifying whether the skill is region-specific or configurable. Because the file provides no surrounding documentation or opt-in mechanism here, the setting is ambiguous and could affect behavior outside a narrowly defined context.

Static analysis

No suspicious patterns detected.