Back to skill

Security audit

OpenClaw Memory Admin

Security checks for vulnerabilities and agentic risk

Overview

The skill does what it says, but it has enough under-scoped access to sensitive long-term memory files that users should review it carefully before installing.

Install only if you intentionally want an agent to administer MemoryOS long-term memory files. Use it with explicit requests, trusted user_id and assistant_id values, and a trusted data root. Back up before writes, treat exports as private data, and prefer a hardened version that validates identifiers, confines paths, disables implicit invocation, and asks before mutating or exporting memory.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/memoryos_admin.py:35
Finding
Path Traversal Through Unsanitized User and Assistant Identifiers<![CDATA[ ## Vulnerability Details **File Location**: `scripts/memoryos_admin.py`, lines 35-40 **Vulnerability Type**: Path traversal and insufficient filesystem boundary validation **Risk Level**: Medium ### Vulnerable Code ```python def user_file(data_root: Path, user_id: str) -> Path: return data_root / "users" / user_id / "long_term_user.json" def assistant_file(data_root: Path, assistant_id: str) -> Path: return data_root / "assistants" / assistant_id / "long_term_assistant.json" ``` ### Technical Analysis The `user_file()` and `assistant_file()` functions directly incorporate command-line-controlled identifiers into filesystem paths. Neither function validates the identifiers or verifies that the resulting paths remain beneath the intended `users` or `assistants` directory. An identifier can contain absolute paths, path separators, or parent-directory components such as `..`. Python's `pathlib` path composition preserves these traversal semantics. Absolute path components may also discard the preceding base path. The resulting untrusted paths are subsequently used by operations that read, create, overwrite, export, or back up MemoryOS data. The affected commands include: - `summary` - `backup` - `search-user` - `search-assistant` - `add-user-knowledge` - `add-assistant-knowledge` - `set-profile` - `export-markdown` For read operations, exploitation requires a targeted file with the expected fixed filename, such as `long_term_user.json` or `long_term_assistant.json`, and valid JSON content where parsing is performed. For write operations, an attacker can create the expected filename in a reachable directory or modify an existing compatible JSON file. Access remains limited to the permissions of the account running the script. Path resolution checks alone are insufficient if writable path components can be replaced with symbolic links. Where tenant or filesystem isolation is required, symlink handling must therefore also be hardened. ## ...[truncated 1811 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Apply a strict identifier allowlist** Permit only characters needed by the identifier format, such as letters, numbers, periods, underscores, and hyphens. Explicitly reject empty identifiers, `.` and `..`. ```python import re ID_PATTERN = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]*$") def validate_id(value: str, field_name: str) -> str: if not ID_PATTERN.fullmatch(value) or value in {".", ".."}: raise ValueError(f"Invalid {field_name}") return value ``` 2. **Enforce containment after canonical path resolution** Resolve the expected base directory and candidate path, then confirm that the candidate remains beneath the expected base. ```python def confined_file(base: Path, identifier: str, filename: str) -> Path: identifier = validate_id(identifier, "identifier") resolved_base = base.resolve() candidate = (resolved_base / identifier / filename).resolve() if not candidate.is_relative_to(resolved_base): raise ValueError("Resolved path escapes the permitted directory") return candidate ``` Use separate bases for users and assistants: ```python def user_file(data_root: Path, user_id: str) -> Path: return confined_file(data_root / "users", user_id, "long_term_user.json") def assistant_file(data_root: Path, assistant_id: str) -> Path: return confined_file( data_root / "assistants", assistant_id, "long_term_assistant.json", ) ``` 3. **Harden against symbolic-link escapes** If directories may be writable by untrusted accounts, reject symbolic links in each existing path component or use descriptor-relative filesystem APIs with no-follow behavior. Revalidate containment immediately before sensitive reads and writes to reduce time-of-check/time-of-use exposure. 4. **Use least-privilege filesystem permissions** Run the administrative script under an a ...[truncated 797 chars]
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (4)

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill clearly instructs direct inspection, backup, export, and mutation of MemoryOS storage files, which implies file read/write capability, but it does not declare an explicit tool scope such as permissions or allowed-tools. That omission weakens least-privilege controls and can let an agent invoke broader filesystem access than reviewers or runtime policy expect, especially because the workflow includes locating arbitrary data roots and modifying persistent memory files.

Vague Triggers

Medium
Confidence
94% confidence
Finding
The skill enables implicit invocation while advertising broad memory administration capabilities such as inspecting, backing up, searching, exporting, and updating long-term memory. That combination can cause the agent to invoke the skill in loosely related contexts and perform sensitive data access or modification without sufficiently explicit user intent, increasing the risk of privacy violations, unauthorized memory changes, or unintended data exfiltration.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The add-user-knowledge, add-assistant-knowledge, and set-profile paths modify long-term memory JSON files on disk via save_json, creating persistent changes to user or assistant data. The code has no confirmation step, warning text, or explanatory comments indicating that these commands permanently alter stored memory records.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script exports user profile and knowledge-base contents into a markdown file, which can expose personal or sensitive long-term memory data. Although the code performs file output, there is no confirmation prompt, warning message, or explanatory comment/docstring alerting the operator that private memory contents will be written to a separate file.

Static analysis

No suspicious patterns detected.