Back to skill

Security audit

Better Memory V2

Security checks for vulnerabilities and agentic risk

Overview

This is a real local memory-management skill, but it makes persistent agent-memory changes and has under-disclosed or unsafe mutation paths that should be reviewed before installation.

Install only if you are comfortable with it modifying persistent workspace memory and agent guidance files. Review AGENTS.md, MEMORY.md, HEARTBEAT.md, .openclaw-memory-os, and the cron template before enabling scheduled runs; avoid using it from oddly named workspace paths; and do not import or capture untrusted memory text until marker handling is fixed.

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)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/emit_cron_template.py:33
Finding

Shell Command Injection Through Unquoted Workspace Path in Generated Cron Template

Content
View full analysis
= threshold", f"{daily_minute} */2 * * * cd {workspace} && python3 skills/better-memory/scripts/run_daily_review.py --workspace . --threshold-only", "", "# 2) Daily L1 -> L2 review (always run)", f"{daily_minute} {daily_hour} * * * cd {workspace} && python3 skills/better-memory/scripts/run_daily_review.py --workspace .", "", "# 3) Weekly L2 -> L3 rollup", f"{weekly_minute} {weekly_hour} * * {weekly_day} cd {workspace} && python3 skills/better-memory/scripts/run_weekly_rollup.py --workspace .", "", "# 4) Monthly advisory review report (no auto cleanup)", f"{monthly_minute} {monthly_hour} {settings['monthly_review_day']} * * cd {workspace} && python3 skills/better-memory/scripts/run_monthly_review.py --workspace .", "", ] ``` ### Technical Analysis The resolved workspace path is interpolated directly into shell command lines without shell quoting. Cron executes each command through a shell, so shell metacharacters in the workspace path can change the command's meaning. For example, a path containing characters such as `;`, `&&`, command substitution syntax, redirection operators, or whitespace can terminate or modify the intended `cd` command. Although this script only generates a template and does not install it automatically, the generated file is explicitly intended to be copied into a cron configuration. Scheduling values are also loaded from `.openclaw-memory-os/config.json` without revalidation inside `emit_cron_template()`. Bootstrap validates in ...[truncated 1399 chars]
Remediation
View remediation

T02 · Agent Memory Poisoning

Warning
Location
scripts/refine_memory.py:270
Finding

Persistent Memory-Block Injection Through Unescaped Managed Delimiters

Content
View full analysis
str: return " ".join(text.replace("|", "/").replace("]", ")").split()) ``` The weekly rollup places the stored topic and statement directly into the managed `MEMORY.md` block: ```python def render_l3_block_from_snapshot(snapshot: dict, settings: dict) -> str: max_l3_per_kind = settings["max_l3_per_kind"] min_evidence_for_l3 = settings["min_evidence_for_l3"] def section(kind: str, heading: str) -> list[str]: lines = [f"## {heading}"] topics = snapshot.get("by_kind", {}).get(kind, {}) if not topics: lines.append("- (empty)") lines.append("") return lines ranked = sorted( topics.items(), key=lambda item: (item[1]["evidence_count"], item[1]["last_seen"]), reverse=True, ) emitted = 0 for topic, row in ranked: if row["evidence_count"] < min_evidence_for_l3: continue lines.append( f"- {topic}: {row['canonical_statement']} " f"(axes={','.join(row['axes'])}, evidence={row['evidence_count']}, last={row['last_seen']})" ) emitted += 1 if emitted >= max_l3_per_kind: break if emitted == 0: lines.append("- (empty)") lines.append("") return lines output = [MANAGED_MEMORY_BLOCK_START] output.extend(section("experience", "L3 Experience")) output.extend(section("value", "L3 Values")) output.extend(section("standard", "L3 Sta ...[truncated 4148 chars]
Remediation
View remediation
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • 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
Findings (11)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The declared description presents a comprehensive memory-management skill covering installation, migration, typed memory capture, daily/weekly distillation, and monthly review/report generation. The supplied code chunk is much more limited: it reads an existing monthly cleanup plan from .openclaw-memory-os/reviews, updates statuses on parsed entries, optionally reruns daily review and weekly rollup, and writes a markdown summary of applied changes. While the optional rerollup aligns partially with ongoing maintenance/distillation, the main behavior is specifically applying monthly cleanup actions, not installing the memory stack, migrating legacy data, capturing memory, or generating the monthly review itself. This is a material description-versus-behavior mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The supplied code chunk is narrowly focused on emitting a cron template file based on configured review times. It schedules other scripts for catch-up, daily review, weekly rollup, and monthly review, but does not itself perform those reviews or any installation/migration/memory-capture tasks described in the skill declaration. The declared purpose is much broader than the behavior shown here, making the description materially inaccurate for this code chunk.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The declared description presents a broad memory installation and maintenance skill for the OpenClaw memory system. The supplied code chunk is much narrower: it reads settings, renders a static guidance block, and upserts that block into HEARTBEAT.md. Although the inserted text references external scripts for refine/rollup/review/cleanup, this code does not execute those workflows or manipulate the memory store itself. Its actual purpose is heartbeat integration/advisory reminder installation, which is only a partial and materially different subset of the declared behavior.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description says this skill performs installation and ongoing maintenance of a memory system, including migration, typed memory capture, distillation, and reporting. The supplied code instead performs the opposite primary function: it uninstalls existing managed integration by stripping marked blocks from specific markdown files and deleting the sidecar directory unless told to keep it. This is a material purpose mismatch, not just an implementation detail. The code's file deletions and integration removal are undeclared in the description, while the described installation/maintenance capabilities are absent from the code chunk.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill advertises multiple Python scripts that read and write workspace files, but the manifest does not declare any explicit tool scope such as permissions or allowed-tools. That weakens containment and reviewability, because consumers cannot easily tell that the skill will modify AGENTS.md, MEMORY.md, daily logs, and sidecar state before invoking it.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The default prompt automatically invokes the skill and instructs it to perform installation plus recurring daily, weekly, and monthly maintenance without clear scoping, confirmation, or safety bounds. In a memory-management skill, this broad activation language can cause unintended persistent modifications, migrations, or summarization actions to occur when the user did not explicitly request each step.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

This code can overwrite files and delete files entirely via write_text() and unlink() when uninstalling managed blocks, but it provides no warning before performing those destructive actions. The only user-facing disclosure appears after changes are already made, so users are not warned in advance that files may be modified or removed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script recursively deletes the sidecar directory with shutil.rmtree() based on a user-supplied workspace path and does so without validation, preview, or confirmation. In the context of a memory-management skill that operates on workspace state, this is risky because a mistaken or adversarially influenced workspace value could cause unintended loss of local artifacts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This Python file performs persistent writes to config.json and state.json under the workspace via write_text, which can modify user/project data. There is no confirmation prompt, logging/print statement, or inline comment/docstring disclosing that these writes occur, so the behavior is not surfaced to the user within this file.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

This code performs a file write that can replace an existing plan file if the user passes --force. While the argument name implies overwrite behavior, there is no explicit confirmation prompt or stronger in-code warning at the point of the destructive action.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
85% confidence
Finding

This block modifies a user data file by appending promoted memory entries, but the write happens silently during processing. Although the script prints a summary afterward, there is no per-operation disclosure in code comments, docstrings, or visible messaging near the write itself.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.