Back to skill

Security audit

Error Guard — Control‑Plane Safety

Security checks for vulnerabilities and agentic risk

Overview

The skill is a disclosed control-plane recovery tool, but its emergency recovery path can kill every visible process session without ownership checks or confirmation.

Install only if you need advanced OpenClaw control-plane recovery. Treat /flush and /recover as destructive operations until patched: they should be limited to skill-owned sessions, require explicit operator authorization or confirmation, preserve accurate success/failure results, and document the risk of losing unrelated in-flight work.

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

T05 · Unauthorized Access and Privilege Escalation

Error
Location
control.ts:58
Finding
Unscoped Emergency Flush Can Terminate Unrelated Process Sessions## Vulnerability Details **File Location**: `control.ts:58-76` **Vulnerability Type**: Missing authorization and process-ownership validation **Risk Level**: High ```ts // /flush: emergency stop export async function flush() { // Mark tasks as cancelled registry.forEach(t => t.state = "cancelled"); registry.clear(); // Kill active exec sessions (best-effort) try { const procs = await process.list({}); for (const p of procs.sessions || []) { await process.kill({ sessionId: p.sessionId }); } } catch (e) { // Swallow errors: flush must always respond } return { ok: true, message: "All tasks cancelled, exec sessions killed, registry cleared", ts: now() }; } ``` ### Technical Analysis The exported `flush()` operation obtains the complete set of process sessions visible through `process.list({})` and passes every returned session identifier to `process.kill()`. It does not verify that a process belongs to a task created or managed by this skill. No caller authorization, process ownership check, task-to-session mapping, protected-session allowlist, or scope restriction is applied before termination. Consequently, the operation crosses the expected least-privilege boundary between error-guard workers and unrelated workloads. The catch block also suppresses every termination error, while the function unconditionally returns `ok: true`. This can conceal partial cleanup and make it difficult to determine which sessions were actually terminated. ### Attack Path 1. An attacker or compromised component gains the ability to invoke the exported `flush()` function or a command handler exposing it as `/flush`. 2. `flush()` calls `process.list({})`, enumerating every process session visible to the SDK caller. 3. The function iterates over the unfiltered session collection. 4. Each session identifier is supplied to `process.kill()`, without checking whether error-guard created or owns that session. 5. Unrelated workloads ...[truncated 716 chars]
Remediation
## Remediation Suggestions 1. Record the process or session identifier returned whenever an error-guard worker is created. 2. Maintain an explicit task-to-session ownership mapping in the control-plane registry. 3. During `flush()`, terminate only session identifiers recorded as owned by active error-guard tasks. 4. Revalidate ownership immediately before every termination to avoid stale-identifier and race-condition issues. 5. Require an authenticated and authorized control-plane caller for destructive operations such as `/flush` and `/recover`. 6. Maintain a denylist of protected control-plane and infrastructure sessions as defense in depth. 7. Clear registry entries only after termination attempts have been recorded; preserve enough state to retry failed cleanup safely. 8. Return an accurate structured result containing terminated, skipped, and failed session identifiers instead of unconditionally reporting success. 9. Add tests confirming that unrelated sessions returned by the SDK are never passed to `process.kill()`.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description says this skill is a safety/control-plane recovery tool for unresponsive systems, with capabilities like inspecting state, flushing queues, canceling work, and recovering from hangs. The code does none of that. It implements a benchmark worker that simulates four benchmark phases (latency, reasoning, coding, long-context), sends started/progress/heartbeat/completed events, and reports failures. Its primary purpose is benchmark execution/telemetry in a sub-agent, which is materially different from the declared recovery and control-plane functionality.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description promises an operational safety/control skill with active recovery capabilities for unresponsive systems. The supplied code chunk is only a passive event protocol definition: it declares task event types, a TaskEvent interface, a timestamp helper, and an event constructor. This is materially different from the claimed primary purpose and lacks the described capabilities. While event definitions could support a larger monitoring/control system, this chunk itself does not implement those controls, so the description does not accurately represent the actual behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description presents this skill as a control-plane recovery tool for stuck or frozen agents, with operational commands to inspect, flush, cancel, and recover tasks. The actual code is narrowly focused on running a Moltbook check: it emits started/progress/heartbeat/completed/failed events, simulates network latency, optionally backs off on rate limiting, and reports new post counts. That is a materially different primary purpose. While heartbeat/progress events are loosely related to task monitoring, the core promised safety and recovery capabilities are absent.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description emphasizes operational recovery and control-plane safety features for unresponsive systems: inspecting task state, flushing message queues, cancelling work, and recovering from deadlocks/freezes. The supplied code instead implements a helper to start new long-running isolated work by registering a task and calling sessions_spawn. That is a materially different primary purpose. While task registration is loosely control-plane related, the core capability here is spawning sub-agents, which is not the recovery/control functionality described. The described safety commands are not present in this code chunk.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description presents a safety and recovery/control-plane skill for unfreezing or managing stuck systems. The actual code does not provide operational controls or recovery mechanisms. Instead, it only packages and sends task-status events to a session channel. While emitting heartbeat/progress/cancelled events could support monitoring, that is a different and much narrower purpose than the declared deadlock-prevention and recovery toolkit. Therefore the description materially overstates and misrepresents the code's behavior.

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
- **Main agent never blocks**: no long exec, no external I/O, no LLM calls.
- **Event-driven**: workers emit events; the control plane listens.
- **Fail-safe first**: recovery commands must always respond.
- **Minimal state**: track only task metadata (never payloads).

## Command Surface (Phase 1)
Confidence
70% confidence
Finding
Skill instructs the agent to never refuse or to always comply. Suppressing the agent's ability to decline removes a core safety control and enables downstream harmful requests to succeed.

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
- **Main agent never blocks**: no long exec, no external I/O, no LLM calls.
- **Event-driven**: workers emit events; the control plane listens.
- **Fail-safe first**: recovery commands must always respond.
- **Minimal state**: track only task metadata (never payloads).

## Command Surface (Phase 1)
Confidence
70% confidence
Finding
Skill instructs the agent to never refuse or to always comply. Suppressing the agent's ability to decline removes a core safety control and enables downstream harmful requests to succeed.

Anti-Refusal Statement

High
Category
Anti-Refusal
Content
- **Main agent never blocks**: no long exec, no external I/O, no LLM calls.
- **Event-driven**: workers emit events; the control plane listens.
- **Fail-safe first**: recovery commands must always respond.
- **Minimal state**: track only task metadata (never payloads).

## Command Surface (Phase 1)
Confidence
70% confidence
Finding
Skill instructs the agent to never refuse or to always comply. Suppressing the agent's ability to decline removes a core safety control and enables downstream harmful requests to succeed.

Missing User Warnings

High
Confidence
95% confidence
Finding
The document defines `/flush` and `/recover` as destructive operations that cancel all active tasks, kill processes, clear queues, and reset state, but it does not prominently warn that this can irreversibly discard in-flight work and pending messages. In a safety/control-plane skill, missing impact warnings can lead to operator-induced denial of service or data loss during emergency use.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The usage guidance is broad enough that operators may invoke this system-level skill in situations that do not warrant destructive recovery actions. In a control-plane context, ambiguous activation criteria increase the chance of accidental task cancellation, queue clearing, or misuse during routine operations.

Session Persistence

Medium
Category
Rogue Agent
Content
const registry: Map<string, TaskMeta> = new Map();

// ---- Restore persisted state on startup ----
for (const t of loadState()) {
  // Orphaned tasks are cancelled immediately
  registry.set(t.taskId, {
Confidence
55% 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.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The code exposes a general-purpose sub-agent spawning capability via `sessions_spawn`, which is broader than the described recovery/control-plane function of the skill. Even though the helper is simple, it accepts arbitrary `message`, `label`, and timeout values and can launch long-running isolated work, increasing the attack surface for unauthorized task execution, privilege expansion, or abuse of agent resources.

Static analysis

No suspicious patterns detected.