Back to skill

Security audit

MeshOps Control Plane

Security checks for vulnerabilities and agentic risk

Overview

This skill fits a mesh-control purpose, but it gives task-driven authority over plugin installs, skill deployment, gateway restarts, and command execution with weak scoping and authorization.

Install only in an operator-controlled OpenClaw environment. Do not enable high-risk gates or accept task files from untrusted sources until caller identity is authenticated outside the task body, plugin and skill sources are allowlisted or signed, archive extraction is hardened, and task/path fields are strictly validated.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
Findings (5)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/handler.py:20
Finding

Spoofable Caller Authorization Allows Impersonation of Privileged Operators

Content
View full analysis
set[str]: raw = os.environ.get("OPENCLAW_ALLOWED_CALLERS", "architect,chief-of-staff") out = set() for part in raw.split(","): v = part.strip() if v: out.add(v) return out def authorize(task: dict) -> tuple[bool, str]: action = str(task.get("action", "")).strip() caller = str(task.get("caller", "")).strip() if not caller: return False, "missing caller" allowed = _allowed_callers() if caller not in allowed: return False, f"caller '{caller}' not authorized" if action in HIGH_RISK_ACTIONS: allow_high_risk = os.environ.get("OPENCLAW_ALLOW_HIGH_RISK", "0") == "1" if not allow_high_risk: return False, f"action '{action}' blocked (set OPENCLAW_ALLOW_HIGH_RISK=1 to enable)" return True, "ok" ``` The task schema also defines `caller` as an ordinary task-controlled string: ```json { "properties": { "task_id": {"type":"string"}, "action": {"type":"string"}, "params": {"type":"object"}, "caller": {"type":"string"}, "correlation_id": {"type":"string"} } } ``` ### Technical Analysis The authorization decision treats the `caller` value embedded in the submitted JSON document as proof of identity. Because the same party submitting or modifying a task can choose this field, an attacker can claim to be any name in `OPENCLAW_ALLOWED_CALLERS`, including the default privileged identities `architect` and `chief-of-staff`. No cryptographic signature, authenticated transport identity, trusted gateway assertion, token, file ownership check, or other mechanism binds the claimed caller to a verified principal. The handler also does not validate the task against `schemas/task.schema.json`, although schema ...[truncated 1814 chars]
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Error
Location
actions/setup-ansible-plugin.sh:9
Finding

Attacker-Selected Plugin Installation Bypasses High-Risk Action Gating

Content
View full analysis
&2 exit 2 fi INSTALL_TARGET="$PLUGIN_REF" ;; *) echo "unsupported source: $SOURCE" | tee -a "$LOG" >&2 exit 2 ;; esac run_cmd "plugin-install" openclaw plugins install "$INSTALL_TARGET" ``` ### Technical Analysis Plugin installation is a code-acquisition and code-execution operation. The task can select a GitHub repository, npm package, or local path, but the implementation does not: - Require `OPENCLAW_ALLOW_HIGH_RISK`. - Require a dedicated plugin-installation gate. - Restrict the reference to an approved package or repository. - Pin the ...[truncated 2160 chars]
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Error
Location
actions/deploy-skill.sh:6
Finding

Downloaded Skill Archive Can Execute Task-Selected Remote Code

Content
View full analysis
/dev/null 2>&1; then SHA_ACT=$(sha256sum "$ARCHIVE" | awk '{print $1}') else SHA_ACT=$(shasum -a 256 "$ARCHIVE" | awk '{print $1}') fi if [ "$SHA_EXPECT" != "$SHA_ACT" ]; then echo "SHA mismatch expected=$SHA_EXPECT actual=$SHA_ACT" | tee -a "$LOG" >&2 exit 4 fi DEST="/opt/openclaw/skills/$NAME" mkdir -p "$DEST" echo "Extracting into $DEST" | tee -a "$LOG" tar -xzf "$ARCHIVE" -C "$DEST" if [ -x "$DEST/test_smoke.sh" ]; then echo "Running smoke test" | tee -a "$LOG" (cd "$DEST" && ./test_smoke.sh) || { echo "Smoke failed" | tee -a "$LOG" >&2; exit 5; } fi ``` ### Technical Analysis The script downloads a task-selected HTTPS resource, extracts it, and executes `test_smoke.sh` if the archive marks that file executable. Although a SHA-256 digest is required, the expected digest is supplied in the same untrusted task as the URL. This protects against accidental corruption or changes relative to the task but does not establish publisher trust. An attacker can create a malicious archive, calculate its SHA-256 digest, and submit both values. HTTPS similarly protects transport confidentiality and integrity but does not prove that the artifact publisher is authorized. Redirects are followed through `curl -L`, and there is no host allowlist, signature verification, provenance validation, content review, or execution sandbox. ### Attack Path 1. Create an archive containing an executable file named `test_smoke.sh`. 2. Put arbitrary commands in that file, for example ...[truncated 1425 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
actions/deploy-skill.sh:5
Finding

Unvalidated Deployment Paths and Archive Entries Can Escape the Intended Skill Directory

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
actions/run-cmd.sh:4
Finding

Unvalidated Task IDs Permit Artifact File Path Traversal Across Actions

Content
View full analysis
`. ### Attack Path 1. Submit a task with a traversal-bearing identifier, such as: ```json { "task_id": "../../../tmp/attacker", "caller": "architect", "action": "run-cmd", "params": { "cmd": "openclaw status" } } ``` 2. The action constructs paths de ...[truncated 1262 chars]
Remediation
View remediation
Vulnerability Patterns
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (14)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The script executes test_smoke.sh directly from the newly deployed artifact, meaning any party controlling the artifact contents can achieve arbitrary code execution on the host as the deploy user. The SHA256 check does not reduce the risk if an attacker can submit both the artifact URL and matching hash in the task file, making this effectively an explicit remote code execution path.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill documents an admin-capable ansible_delete_messages tool as an emergency purge mechanism but does not pair it with explicit destructive-operation warnings, confirmation requirements, or recovery limitations. In a distributed coordination system where shared messages are durable state and part of operational evidence, this omission increases the risk of accidental or socially engineered deletion of important audit trails and active work context.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% 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 · SKILL.md (reported line 114)May include surrounding context.

md
| Tool | Purpose |
|------|---------|
| `ansible_delegate_task` | Create task for another node/agent set |
| `ansible_claim_task` | Claim pending task |
| `ansible_update_task` | Update task status/progress |
| `ansible_complete_task` | Complete task and notify requester |

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The retention/pruning feature is described as routine lifecycle management without clearly warning that configuration changes can permanently remove closed-task history and coordination evidence. Because this skill emphasizes durable shared state and auditability, understated pruning semantics can lead to unintended data loss, weakened forensics, or premature deletion of operational records.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The script extracts a remotely downloaded archive directly into the skills directory after only verifying a supplied hash, but it does not validate archive contents for path traversal, symlinks, ownership, or dangerous file placement. A crafted tarball can overwrite unexpected files within the destination tree or plant executable content that will later be trusted as part of a deployed skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The script serializes multiple environment-derived values, including caller allowlists and action gating flags, into a persistent artifact file. While this is likely intended for diagnostics, it can expose internal policy configuration and operational controls to any actor who can read artifacts, which may aid reconnaissance or policy circumvention attempts.

Content

No source excerpt is available for this finding.

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · docs/ansible-coding-skill-spec.md (reported line 251)May include surrounding context.

md
"action": "scaffold",
    "branch": "skills/feature/secrets-mgmt",
    "files_created": [
      "skills/openclaw-skill-ansible/subskills/secrets-mgmt/SKILL.md",
      "playbooks/secrets-mgmt.yml",
      "roles/vault/tasks/main.yml"
    ],

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 · docs/ansible-coding-skill-spec.md (reported line 501)May include surrounding context.

"status": "failed", "issues": [ "Git branch creation failed: branch already exists", "Cannot write to repository: permission denied" ] }

text

Skill Enumeration

Medium
Category
Agent Snooping
Confidence
80% confidence
Finding

Skill enumerates or reads other installed skills. Access to other skills' SKILL.md files or the skills directory reveals prompt instructions, capabilities, and secrets that should be invisible to peer skills.

Content

Scanner excerpt · docs/ansible-coding-skill-spec.md (reported line 690)May include surrounding context.

md
### Skill Loading

OpenClaw loads `SKILL.md` files from:
- `~/.openclaw/workspace/skills/ansible/SKILL.md` — core coordination skill
- `~/.openclaw/workspace/skills/ansible/skills/*/SKILL.md` — skill catalog entries

Agents receive skill context when:

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The requester-side auto-invocation rule is intentionally broad: agents are told to delegate any work that 'falls under a registered capability' before proceeding. In a shared multi-agent mesh, this can cause over-delegation of sensitive, user-scoped, or partially understood tasks to any agent advertising a matching capability, increasing the chance of unintended data exposure, privilege boundary crossing, or unsafe task fan-out. The surrounding skill context makes this more dangerous because capability registration is automatic and discovery is global via shared Yjs state, so the triggering surface is large and dynamic.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The executor-side rule says to claim the first unclaimed task matching a registered capability and process it before any other work, but the matching criteria and safety gates are underspecified. In practice, any agent with that capability may automatically claim and execute tasks without validating origin, authorization, scope, or whether the task is actually appropriate for that executor, creating a confused-deputy risk and enabling unintended task handling. This context increases danger because tasks are sourced from shared replicated state and capability loading auto-registers executors, so accidental or unauthorized claiming can happen across gateways.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The module documentation presents the component as a secure dispatcher, but the implementation is fundamentally a shell-script launcher whose behavior can include explicitly high-risk actions. That is not merely incomplete documentation: the 'secure' characterization conflicts with the fact that the code enables command and deployment execution when environment gates permit it.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · src/handler.py (reported line 60)May include surrounding context.

python
return 2

    # Run script directly with argv, never shell interpolation.
    result = subprocess.run(["/bin/bash", str(script), task_path], check=False)
    return int(result.returncode)

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
78% confidence
Finding

This file is documentation, so the only applicable mismatch class is documentation-to-documented-capability divergence. The guidance at L97-L98 frames operations as preferring managed, auditable paths and explicitly gating high-risk execution, yet the same document enumerates a broad set of direct state-mutating commands such as messages-delete, admin setters, retention changes, token issuance, and agent rebind/disable flows. While not a hard contradiction in code, the notes present a narrower operational posture than the capabilities actually listed.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.