Back to skill

Security audit

Claw Self Improving Plus

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent, but it can write durable agent behavior and memory files using an approval flag stored in the same editable patch file.

Review every generated patch before applying it, only run `apply_approved_patches.py` on patch files you control, prefer `--dry-run` first, and avoid promoting untrusted user or web content into `SOUL.md`, `AGENTS.md`, `TOOLS.md`, or `MEMORY.md` without manual verification.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Findings (1)

T02 · Agent Memory Poisoning

Error
Location
scripts/apply_approved_patches.py:30
Finding
Untrusted Patch Approval Allows Persistent Agent Memory and Instruction Poisoning<![CDATA[ ## Vulnerability Details **File Location**: `scripts/apply_approved_patches.py:30-80` **Vulnerability Type**: Approval integrity failure permitting persistent instruction injection **Risk Level**: High ### Vulnerable Code ```python def validate_patch(patch: dict): target = patch.get("target_file") if target not in TARGETS: return f"target_file not allowed: {target}" if not patch.get("approved"): return "not approved" if not (patch.get("suggested_entry") or (patch.get("old_text") is not None and patch.get("new_text") is not None)): return "no applicable patch content" return None def apply_patch(base_dir: Path, patch: dict, dry_run: bool = False): error = validate_patch(patch) if error: return {"id": patch.get("id"), "status": "skipped" if error == "not approved" else "error", "reason": error} path = base_dir / patch["target_file"] path.parent.mkdir(parents=True, exist_ok=True) if not path.exists() and not dry_run: path.write_text("", encoding="utf-8") text = path.read_text(encoding="utf-8") if path.exists() else "" old_text = patch.get("old_text") new_text = patch.get("new_text") suggested_entry = patch.get("suggested_entry") anchor = patch.get("anchor") insert_mode = patch.get("insert_mode", "append") if suggested_entry and suggested_entry in text: return {"id": patch.get("id"), "status": "skipped", "reason": "entry already present", "target": str(path)} if old_text is not None and new_text is not None: if old_text not in text: return {"id": patch.get("id"), "status": "error", "reason": "old_text not found", "target": str(path)} updated = text.replace(old_text, new_text, 1) if not dry_run: path.write_text(updated, encoding="utf-8") return {"id": patch.get("id"), "status": "applied", "mode": "replace", "target": str(path), "dry_run": dry_run} if suggested_entry and ...[truncated 3787 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Separate approval records from patch content** - Store approvals in a distinct, access-controlled file or trusted approval service. - Do not treat a Boolean embedded in the candidate document as authoritative. 2. **Cryptographically bind approval to exact content** - Canonicalize each patch and calculate a strong hash over its identifier, target, mode, anchor, old text, and new content. - Record the hash when the reviewer approves the patch. - Recalculate and compare the hash immediately before application. - Reject any patch changed after approval. 3. **Require final-diff confirmation** - Render the exact destination path and final diff immediately before writing. - Require explicit confirmation for each patch, especially changes to `SOUL.md`, `AGENTS.md`, `TOOLS.md`, and `MEMORY.md`. - For non-interactive automation, require a separately generated signed approval artifact. 4. **Validate patch structure and semantics** - Enforce a strict JSON schema, including exact Boolean types, permitted insertion modes, size limits, and required fields. - Flag instruction-like content involving safety overrides, credential access, destructive commands, external payloads, or privilege changes for elevated review. - Reject ambiguous or malformed replacement operations. 5. **Harden filesystem writes** - Resolve and verify the base directory and destination paths. - Reject symbolic-link destinations or use no-follow file operations to prevent unexpected redirection. - Write through a temporary file in the same directory and atomically replace the destination. - Create restricted-permission backups and provide a rollback mechanism. 6. **Improve auditability** - Record the reviewer identity, timestamp, canonical patch hash, destination file hash before and after modification, and exact applied diff. - Keep append-only or tamper-evident audit logs. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (9)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description is about capturing lessons from mistakes, deduplicating learnings, drafting promotion candidates for files like SOUL.md/AGENTS.md/TOOLS.md/MEMORY.md, and enforcing human approval before persistent edits. The supplied code does none of that. Instead, it processes backlog data by joining timestamps from another file, computing age in days, assigning stale-status labels, decrementing priority scores for stale items, and emitting a reordered JSON backlog. This is a materially different primary purpose, with capabilities unrelated to self-improvement learning capture or candidate patch generation.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description describes a higher-level learning-management and approval system for capturing lessons and proposing controlled memory updates. The supplied code does none of that. It only takes an input file path and archives the file by copying or moving it into an archive directory with a timestamped name. This is a materially different primary purpose, not merely a supporting utility as presented, because the code chunk itself implements only file archival and none of the declared learning, deduplication, scoring, patch drafting, or approval behaviors.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding
The code partially matches the description: it does process raw learning-like records and score reuse value, confidence, scope, promotion worthiness, and target candidates. However, the declared description presents a broader end-to-end conservative self-improvement workflow with deduplication, patch drafting for specific long-term memory files, and an approval step before edits. This script does none of those workflow-critical actions; it only parses JSONL and annotates entries with heuristic metadata. Because several central declared capabilities are absent, the description materially overstates what this code chunk actually does.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill references shell execution plus file read/write workflows and scripts, but it does not declare any explicit tool scope such as permissions or allowed-tools. That creates unnecessary ambiguity about what capabilities the skill may exercise, increasing the chance an agent executes filesystem or shell actions more broadly than intended.

Persistent Context Injection

Medium
Category
Memory Poisoning
Content
1. `reuse_value`: will this help again?
2. `confidence`: how well supported is it?
3. `impact_scope`: how broadly does it matter?
4. `promotion_worthiness`: should it become a lasting rule or memory?
5. `promotion_target_candidates`: where should it go if promoted?

Use this practical rubric:
Confidence
86% confidence
Finding
The skill is explicitly designed to promote observations into persistent files such as SOUL.md, AGENTS.md, TOOLS.md, and MEMORY.md, which can inject durable behavioral context into future sessions. Even with an approval step, a flawed or poisoned learning candidate could cause long-term persistence of incorrect instructions, unsafe preferences, or attacker-influenced memory that affects later agent behavior.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def run(cmd):
    subprocess.run(cmd, check=True)


def main():
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The manifest describes a workflow that drafts candidate patches, reviews them through an approval step, and keeps human control before any long-term file edits. This script goes beyond merely preparing review artifacts by invoking `apply_approved_patches.py` when `--apply` is provided, which performs the actual edits to the target base directory. That write/apply behavior is more powerful than a purely conservative capture-and-review pipeline as described at the manifest level.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
This code performs an archival operation on the user-supplied input file when `--archive-input` is set, which affects user data by moving it into an archive directory. Although the flag name hints at the behavior, there is no confirmation prompt, warning print, or descriptive comment/docstring disclosing that the original inbox will be archived after processing.

Context-Inappropriate Capability

Low
Confidence
76% confidence
Finding
The stated purpose centers on turning mistakes and corrections into structured learnings, deduplicating them, and preparing promotion candidates under human control. The optional `--archive-input` step adds input archival and retention management, which is operational housekeeping rather than an obvious core requirement of conservative self-improvement analysis and promotion review.

Static analysis

No suspicious patterns detected.