Back to skill

Security audit

Error Monitor Fix

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly aligned with OpenClaw error monitoring, but it persistently copies log-derived content into workspace files without redaction and has incomplete scope and install disclosure.

Install only if you are comfortable with OpenClaw error logs being copied into persistent workspace files. Before use, add redaction and Markdown escaping, document the dotfiles and fixed diagnostic commands, and resolve the missing postinstall script or remove that install hook.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • 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)

T02 · Agent Memory Poisoning

Warning
Location
scripts/monitor-error.js:86
Finding
Untrusted log content is written into persistent workspace memory without sanitization<![CDATA[ ## Vulnerability Details **File Location**: `scripts/monitor-error.js`, lines 86-91 and 189-201 **Vulnerability Type**: Persistent Markdown injection / memory poisoning **Risk Level**: Medium ### Vulnerable Code ```javascript for (const key of Object.keys(obj)) { if (key === '_meta' || key === 'time') continue; parts.push(typeof obj[key] === 'string' ? obj[key] : JSON.stringify(obj[key])); } message = parts.join(' | '); for (const err of errors) { const time = err.timestamp.slice(11, 19); const shortMsg = err.message.slice(0, 80).replace(/\|/g, '\\|'); const errorType = err.hash.split(':')[1] || 'unknown'; lines_out.push(`| ${time} | ${err.subsystem || '-'} | ${errorType} | ${shortMsg} |`); } lines_out.push(''); lines_out.push('---'); lines_out.push(''); fs.appendFileSync(ERROR_FILE, '\n' + lines_out.join('\n')); ``` ### Technical Analysis The monitor treats fields from JSON error logs as trusted text and appends them to `~/.openclaw/workspace/error.md`, which is a persistent file inside the agent workspace. Only pipe characters in the shortened message are escaped. Markdown control characters, HTML, line breaks, links, headings, and instruction-like text are not sanitized. The `subsystem` field is also inserted into the Markdown table without any escaping. It is derived from log content at lines 95-106 and can therefore affect the generated document when an attacker can influence logged values. Because the destination is a workspace Markdown file, the injected content may later be presented to an agent or user as trusted monitoring history. If workspace memory files are supplied to an agent in later sessions, attacker-controlled log text can become persistent prompt content. The code does not label entries as untrusted data or enforce a serialization format that separates data from instructions. The message is truncated to 80 characters when persisted, but this does not prevent short instruction payloads, Markdown structure manip ...[truncated 1691 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Treat every log field as untrusted data. 2. Store findings in a structured format such as JSON rather than directly generating agent-consumable Markdown. 3. If Markdown output is required, escape all Markdown and HTML metacharacters in every interpolated field, including `subsystem`, timestamp, error type, and message. 4. Normalize or remove carriage returns, line feeds, Unicode line separators, and control characters before output. 5. Apply strict length limits to all fields, especially `subsystem`. 6. Add a fixed warning around generated content stating that log entries are untrusted evidence and must never be interpreted as instructions. 7. Keep operational logs outside directories automatically loaded as agent memory. Provide them through a dedicated viewer or tool response instead. 8. If an agent must consume the file, pass records through a data-only interface and explicitly instruct the agent not to follow instructions found inside log values. 9. Add tests covering payloads with newlines, headings, links, HTML, table delimiters, code fences, and short prompt-injection phrases. A defensive helper could normalize fields before formatting: ```javascript function sanitizeLogField(value, maxLength = 200) { return String(value ?? '') .replace(/[\r\n\u2028\u2029]+/g, ' ') .replace(/[\x00-\x1F\x7F]/g, '') .replace(/[\\`*_[\]{}()#+.!|<>-]/g, '\\$&') .slice(0, maxLength); } ``` Apply this helper to every value interpolated into `lines_out`. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/monitor-error.js:86
Finding
Potentially sensitive error-log contents are persisted and printed without redaction<![CDATA[ ## Vulnerability Details **File Location**: `scripts/monitor-error.js`, lines 86-91 and 199-211 **Vulnerability Type**: Plaintext sensitive-data exposure through generated reports and console output **Risk Level**: Medium ### Vulnerable Code ```javascript for (const key of Object.keys(obj)) { if (key === '_meta' || key === 'time') continue; parts.push(typeof obj[key] === 'string' ? obj[key] : JSON.stringify(obj[key])); } message = parts.join(' | '); // ... fs.appendFileSync(ERROR_FILE, '\n' + lines_out.join('\n')); // 输出报告 console.log(`⚠️ 发现 ${errors.length} 条新错误:`); console.log(''); for (const err of errors) { console.log(` 🔴 [${err.subsystem || 'system'}] ${err.hash.split(':')[1]}`); console.log(` ${err.message.slice(0, 100)}`); console.log(''); } ``` ### Technical Analysis The parser concatenates every top-level property except `_meta` and `time`. Object values are serialized with `JSON.stringify()`. There is no allowlist and no redaction for common secret-bearing fields such as: - `authorization` - `cookie` - `token`, `access_token`, or `refresh_token` - API keys - Passwords - Session identifiers - Request or response bodies - User-supplied personal data The resulting text is written in plaintext to `~/.openclaw/workspace/error.md` and printed to standard output. Console output may itself be captured by cron, service, CI, or system logs, creating additional copies. Although persisted descriptions are truncated to 80 characters and console messages to 100 characters, credentials and tokens can fit entirely or partially within those limits. Truncation is not a substitute for redaction. The append-only report also increases data retention beyond the lifetime of the source log. No explicit restrictive mode is used when creating `error.md`. Its effective permissions depend on the process umask and any pre-existing file permissions. ### Attack Path 1. A runtime error includes a credential, authorization header, session value, ...[truncated 1310 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace broad field concatenation with a strict allowlist of fields known not to contain secrets. 2. Recursively redact sensitive keys before serialization. Matching should be case-insensitive and include authorization, cookie, token, secret, password, credential, API-key, and session variants. 3. Redact credential patterns embedded in free text, including bearer tokens, JWTs, URL credentials, query-string secrets, private keys, and common API-key formats. 4. Avoid logging raw request or response bodies. 5. Create private output files explicitly and verify existing permissions: ```javascript fs.appendFileSync(ERROR_FILE, output, { mode: 0o600 }); fs.chmodSync(ERROR_FILE, 0o600); ``` 6. Store reports in a dedicated protected directory rather than a generally consumed workspace. 7. Do not print raw error messages to standard output. Print a generated event identifier and a redacted summary instead. 8. Define retention limits and rotate or delete old reports. 9. Document that upstream components must not include credentials in exceptions or ERROR logs. 10. Add automated tests using representative API keys, cookies, JWTs, passwords, and nested secret fields to verify complete redaction. For example, recursively sanitize structured records before constructing a message: ```javascript const SENSITIVE_KEY = /authorization|cookie|token|secret|password|credential|api[-_]?key|session/i; function redact(value, key = '') { if (SENSITIVE_KEY.test(key)) return '[REDACTED]'; if (Array.isArray(value)) return value.map(item => redact(item)); if (value && typeof value === 'object') { return Object.fromEntries( Object.entries(value).map(([k, v]) => [k, redact(v, k)]) ); } return value; } ``` ]]>
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • 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
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (14)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill is presented as monitoring and recommending fixes, but the findings indicate undeclared writes to workspace files and deduplication state, while the documented output and actual behavior do not consistently match. Hidden persistence and logging behavior can leak sensitive operational data, create unauthorized local state, and mislead users about what the skill does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The skill is presented as monitoring and recommending fixes, but the findings indicate undeclared writes to workspace files and deduplication state, while the documented output and actual behavior do not consistently match. Hidden persistence and logging behavior can leak sensitive operational data, create unauthorized local state, and mislead users about what the skill does.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill declares no explicit tool scope or permissions even though the documented behavior implies access to environment-dependent capabilities and local system context. In an agent framework, missing scope declarations can cause the skill to run with broader privileges than users expect, reducing transparency and increasing the chance of unintended access.

Natural-Language Policy Violations

Medium
Confidence
92% confidence
Finding
The manifest description and main body are written as Chinese-only operational instructions, including the skill title and behavior description. Under the policy, language constraints should either offer user opt-in/choice or be clearly justified as region-specific, which is not present here.

Intent-Code Divergence

Medium
Confidence
90% confidence
Finding
The documentation states that repair strategies no longer perform filesystem modifications, yet it also says the skill appends to an error file. This inconsistency undermines trust and can cause reviewers or users to underestimate the write capabilities of the skill, leading to unsafe approval decisions.

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
One section claims manual-only repair, while another says the skill attempts automatic fixes. In a security-sensitive automation environment, contradictory descriptions of autonomy are dangerous because they obscure whether the skill may take actions without user confirmation.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The natural-language header, usage notes, and user-facing messages are written entirely in Chinese, which effectively constrains the skill's interaction language. There is no opt-in, language selection, or documented reason that this skill must be Chinese-only, so it conflicts with the locale-policy requirement.

Intent-Code Divergence

Medium
Confidence
92% confidence
Finding
The header claims the skill only provides manual or read-only guidance, but the implementation persists execution history to a workspace file. This mismatch can mislead users and reviewers about side effects, and the stored history may reveal operational error metadata over time.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The skill description suggests passive log scanning and repair suggestions, but the code executes local shell commands such as ss, grep, awk, and openclaw sessions cleanup --dry-run. Even if intended as read-only checks, invoking system commands expands the attack surface and can produce unintended effects or trust-boundary violations in an agent context.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The script stores a persistent fix history containing timestamps, error counts, and applied actions derived from recent logs without any warning or consent. Operational logs can contain sensitive system state or incident details, so persisting derived data increases exposure and retention risk if the workspace is later accessed by another process or user.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The manifest description says the skill provides 'OpenClaw 系统级错误修复建议', which implies producing repair guidance. In the implementation, scanErrors only parses log entries, deduplicates them, prints summaries, and appends markdown rows to error.md; no logic exists to infer fixes, suggest actions, or map errors to remediation steps.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
The script formats timestamps using the fixed locale 'zh-CN' and timezone 'Asia/Shanghai', which forces a specific language/locale behavior regardless of user preference or system settings. This is a natural-language policy issue because the file does not offer any locale choice or document an opt-in for this restriction.

Intent-Code Divergence

Low
Confidence
73% confidence
Finding
L30 describes an `auto-fix.js` module for automatic repair with five strategies, suggesting broader automated remediation capability. L43 then says cache cleanup and permission repair belong to other agents and are not part of this skill. This creates contradictory documentation about the breadth of remediation handled by this skill.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The description is written entirely in Chinese, which indicates a fixed language presentation without any opt-in or alternate locale. The file provides no indication that the skill is region-specific or that users can choose their language, which can violate language/locale policy requirements.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/auto-fix.js:66