Back to skill

Security audit

Openclaw Self Learning Skill

Security checks for vulnerabilities and agentic risk

Overview

This skill is framed as local self-learning memory, but it also ships a broad command wrapper and persistent raw logs that users should review before installing.

Install only if you are comfortable with a local skill retaining failure details across sessions and with its wrapper being able to run local commands when invoked. Review and protect ~/.openclaw learning files, avoid logging secrets or tokens, and do not enable cron or auto-fix style workflows without human review.

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 (2)

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
skill_wrapper.py:24
Finding

Undeclared Arbitrary Local Process Execution

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:6; skill_wrapper.py:24-29; skill_wrapper.py:71-73
Vulnerability Type: Undeclared command-execution capability that exceeds the manifest's stated permissions
Risk Level: Medium

Vulnerable Code

SKILL.md:6 declares only file access:

yaml
permissions: ["file.read", "file.write"]

skill_wrapper.py:24-29 executes a caller-selected process:

python
result = subprocess.run(
    command,
    capture_output=True,
    text=True,
    timeout=60
)

skill_wrapper.py:71-73 derives that process and its arguments from the unrestricted --call value:

python
command = args.call.split()

result = run_skill(args.skill, command)

Technical Analysis

The Skill manifest declares only file read and write permissions, but the implementation can invoke any executable accessible to the current user. This violates least privilege and prevents consumers from accurately assessing the Skill's effective authority.

The implementation does not use shell=True, so shell metacharacters such as pipes and command substitutions are not interpreted directly. This reduces conventional shell-injection exposure, but it does not remove the underlying arbitrary process-execution capability: the first token supplied through --call selects the executable, and the remaining tokens become its arguments.

Attack Path

  1. An attacker, untrusted workflow, or compromised agent influences the value passed to --call.
  2. args.call.split() converts the supplied string into an executable name and argument list.
  3. run_skill() passes that list directly to subprocess.run().
  4. The selected local executable runs with the privileges and environment of the user invoking the wrapper.
  5. The process can access files, credentials, network resources, and operating-system interfaces available to that user, irrespective of the manifest's narrower pe ...[truncated 744 chars]
Remediation
View remediation

Remediation Suggestions

  1. Explicitly declare process-execution capability in the Skill manifest so users and policy engines can make an informed authorization decision.
  2. Replace unrestricted executable selection with an allowlist of approved programs.
  3. Validate arguments for each approved program using command-specific schemas; reject unexpected options, paths, and argument counts.
  4. Do not construct executable requests from untrusted natural-language or task input without an explicit confirmation boundary.
  5. Resolve and verify executable paths rather than relying on an attacker-influenced PATH.
  6. Run wrapped processes in a least-privilege sandbox with a restricted environment, filesystem view, network policy, and resource limits.
  7. Continue using argument-vector execution without shell=True.
  8. Consider changing the API to accept a structured command identifier and validated arguments rather than a free-form --call string.

T09 · Insecure Skill Coding Practices

Warning
Location
skill_wrapper.py:32
Finding

Persistent Plaintext Logging of Commands, Output, Errors, and Stack Traces

Content
View full analysis

Vulnerability Details

File Location: skill_wrapper.py:32-42; self_learning.py:78-88; self_learning.py:94-106
Vulnerability Type: Sensitive information exposure through unredacted persistent logs
Risk Level: Medium

Vulnerable Code

skill_wrapper.py:32-42 records complete command arguments and raw process error output:

python
log_success(skill_name, {"command": " ".join(command)}, result.stdout)
return {"success": True, "output": result.stdout, "failure_id": None}
else:
    # Log the failure
    error_msg = result.stderr or result.stdout
    fid = log_failure(
        skill_name,
        Exception(error_msg),
        {"command": " ".join(command), "returncode": result.returncode},
        stack_trace=None
    )

self_learning.py:78-88 persists error messages, caller-provided context, and stack traces:

python
entry = {
    "failure_id": failure_id,
    "skill_name": skill_name,
    "error_type": type(error).__name__,
    "error_message": str(error),
    "context": context,
    "stack_trace": stack_trace or traceback.format_exc(),
    "timestamp": datetime.now().isoformat(),
    "status": "pending_analysis"
}

# Append to context log
log = json.load(open(CONTEXT_LOG)) if CONTEXT_LOG.exists() else {}
log[failure_id] = entry
json.dump(log, open(CONTEXT_LOG, "w"))

self_learning.py:94-106 also stores the first 200 characters of successful output:

python
entry = {
    "skill_name": skill_name,
    "context": context,
    "result_summary": str(result)[:200],
    "timestamp": datetime.now().isoformat()
}

success_log = LEARNING_DIR / "success_log.json"
log = json.load(open(success_log)) if success_log.exists() else {}
key = f"{skill_name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
log[key] = entry
json.dump(log, open(success_log, "w"))

Technical Analysis

The wrapper persists complete command strings, raw stand ...[truncated 2076 chars]

Remediation
View remediation

Remediation Suggestions

  1. Redact sensitive command options and values before logging, including passwords, tokens, API keys, authorization headers, cookies, and private-key material.
  2. Do not persist raw standard output, standard error, or stack traces by default. Store only a sanitized error class, exit status, and non-sensitive diagnostic code.
  3. Make full-context logging an explicit opt-in feature with a clear warning about sensitive-data retention.
  4. Create the learning directory with mode 0700 and log files with mode 0600, independent of the ambient umask.
  5. Use secure file creation and atomic replacement to avoid unintended permission inheritance and partially written records.
  6. Implement configurable retention, rotation, maximum file sizes, and secure deletion.
  7. Provide callers with structured context fields and allowlist which fields may be persisted instead of accepting arbitrary context dictionaries.
  8. Add automated tests verifying that representative secrets are removed from command strings, output, exceptions, and stack traces.
  9. Document the actual storage location and the types of data retained so users can review and protect the files appropriately.
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (30)

Scope Creep

Critical
Category
Not specified by scanner
Confidence
99% confidence
Finding

The skill executes subprocesses despite declaring only file.read and file.write permissions, creating a critical capability mismatch. In the context of an agent skill, this allows command execution under the cover of a lower-risk permission set, which can enable arbitrary local actions, data access through other programs, and policy circumvention.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README explicitly demonstrates wrapping arbitrary subprocess execution inside a 'self-learning' skill and logging/learning from the results. For a skill whose stated purpose is persistent memory and self-improvement, broad command execution is an unnecessary capability expansion that can be repurposed to run unrelated or dangerous commands under the guise of learning.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The wrapper is described as able to 'run any skill command' with '--auto-fix', combining arbitrary execution with automated follow-on actions. In context, this creates a dangerous generalized executor rather than a bounded memory skill, increasing the chance of privilege misuse, unintended destructive actions, or abuse if command inputs or learned fixes are influenced by untrusted data.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

The declared description focuses on persistent memory and self-improvement through writing/refining memory files. The provided code's primary function is different: it is a command wrapper that runs arbitrary skill commands via subprocess, captures outputs/errors, logs outcomes, and optionally invokes learning and auto-fix routines after failures. While the logging/learning behavior is related to self-improvement, the significant undeclared capability is execution of arbitrary external commands, which is central to this wrapper's behavior and not reflected in the description or permissions. Therefore the description does not accurately represent the code chunk's actual behavior.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
98% confidence
Finding

The file contains command-execution capability while the manifest declares only file.read and file.write permissions. This mismatch undermines any permission-based trust model because users or orchestrators may grant the skill assuming it cannot spawn processes when in fact it can.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The implementation is a generic command runner with logging rather than a component solely for managing memory files. In security terms, hidden general-purpose execution behind a benign description is dangerous because it can bypass user expectations and platform controls tied to the manifest and description.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

This wrapper can execute arbitrary commands passed through --call, which is far broader than the described function of persistent memory and self-improvement. That scope expansion makes the skill usable as a general execution proxy, increasing the blast radius well beyond file management.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Advocating capture of failure 'full context' and system state encourages retention of raw operational data that often includes secrets, user inputs, internal paths, and transient credentials. Because the skill's purpose is persistent learning, this risk is amplified: sensitive data is not only collected but retained and reused in later analysis workflows.

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 · README.md (reported line 56)May include surrounding context.

Step 1: Set Up Your Project

bash
mkdir self-learning-skill && cd self-learning-skill
cp /path/to/self_learning.py .
cp /path/to/skill_wrapper.py .

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

The statement suggests the solution is self-contained within the standard library, but the examples immediately depend on invoking external commands such as my-skill via subprocess. While technically subprocess is in the standard library, the documented behavior materially depends on external executables, which contradicts the implication of being dependency-free in operation.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README instructs users to log failures with 'full context,' including arguments, state, raw errors, and stack traces, but gives no warning that those fields often contain secrets, personal data, file paths, tokens, or proprietary content. Persistent storage of such material creates a realistic confidentiality risk, especially because this skill is explicitly designed to retain and analyze it over time.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The logging schema explicitly stores complete error details, stack traces, timestamps, and arbitrary context in persistent files under the user's home directory. This creates a concrete data exposure surface because these files can accumulate secrets and sensitive operational context, and later tooling may read, summarize, or propagate that information.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The documentation promotes automatic application of learned fixes without emphasizing that such changes may be broad, destructive, or incorrect. In a self-modifying or self-remediating system, absence of warnings and safety interlocks materially increases the likelihood of unsafe operator behavior and unintended damage.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The reporting workflow encourages reviewing and summarizing accumulated learning files, which may contain previously captured sensitive failure data. Even if the report shows aggregates, report-generation code frequently accesses raw records, increasing the chance of unintended disclosure through console output, summaries, or secondary logs.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The cron integration schedules unattended 'fix-all' behavior that applies learned changes across accumulated failures. Automated recurring remediation broadens impact from a single incident to repeated workspace-wide changes, which is risky for a memory skill because mistakes, poisoned logs, or bad pattern matches can propagate without human review.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill advertises persistent memory and self-improvement through file writes but does not prominently warn users that session data may be stored across runs. This creates a privacy and consent problem because users may disclose sensitive information without realizing it will be retained locally and reused later.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger conditions are broad enough to activate during routine sessions, failures, and repeated mistakes, which makes the scope of autonomous persistence unclear. In practice this can cause the agent to capture and write sensitive or irrelevant context far more often than a user expects, increasing privacy and integrity risk.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The skill explicitly instructs the agent to log failures with full context, system state, user corrections, and repeated error patterns, all of which can easily contain secrets, personal data, or proprietary information. Persisting this material without minimization, filtering, or retention controls materially increases the chance of sensitive data exposure through local compromise, later prompts, or accidental sharing.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
89% confidence
Finding

The skill establishes cross-session persistence of generated lessons and prevention rules, allowing prior outputs to influence future behavior over time. Without trust boundaries, review, or provenance controls, incorrect, manipulated, or sensitive memory entries can persist and steer later agent actions in unsafe ways.

Content

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

md
1. **Capture** — After each session or failure, log: what was attempted, what went wrong, system state
2. **Analyse** — Identify the root cause pattern, not just the symptom
3. **Generate** — Create a fix or prevention rule based on the pattern
4. **Validate** — Test the fix before committing it to memory
5. **Commit** — Update the agent's memory files only when validation succeeds

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The top-level documentation says the system 'applies fixes across all similar cases,' and the architecture diagram presents 'Fix Applied' as an actual remediation step. However, the implementation later only marks failures as 'fix_applied' and stores a text hint, with an inline note admitting that a real implementation would trigger a retry instead.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill persists full failure context, error messages, and stack traces to disk under a predictable location in the user's home directory without sanitization or consent. In an agent setting, context frequently contains secrets, file paths, prompts, tokens, API responses, or personal data, so this creates a local sensitive-data exposure risk and long-term retention issue.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The apply_learned_fixes docstring says it will 'apply learned fixes' and return what was fixed. Yet inside the loop, the comment at L237 concedes that the code merely marks items as fixed in the log and does not actually trigger remediation, creating a direct intent-versus-behavior contradiction.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The docstring for learn_from_failure says step 4 is to 'Apply fixes to all of them.' In practice, apply_learned_fixes only writes 'status' and 'fix_applied' fields into the context log, so the function does not carry out actual fixes on failed cases.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
92% confidence
Finding

The code executes a user-provided command via subprocess.run after only splitting the input string, which gives the skill broad command-execution capability. Even without shell=True, this enables launching arbitrary binaries and exceeds the skill’s stated persistent-memory purpose, creating a strong path to misuse or privilege expansion through the host environment.

Content

Scanner excerpt · skill_wrapper.py (reported line 24)May include surrounding context.

python
Returns {"success": bool, "output": str, "failure_id": str or None}
    """
    try:
        result = subprocess.run(
            command,
            capture_output=True,
            text=True,

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

Automatic application of learned fixes modifies state without a clear user-facing warning or confirmation at the moment changes are applied. In a self-modifying or self-learning skill, silent state changes can introduce unsafe persistence, accidental corruption, or unreviewed behavioral drift.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.