Back to skill

Security audit

Hierarchical Memory

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly a disclosed memory organizer, but its helper script can be misused to overwrite or append to files outside the intended memory folders.

Review this before installing. The memory-management idea is coherent and there is no evidence of network access or hidden code execution, but the helper script should be fixed before use: restrict branch names, resolve paths with containment checks, reject traversal and absolute paths, constrain parent files to memory/domains, and avoid overwriting existing files by default.

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

Error
Location
scripts/add_branch.py:12
Finding

Path Traversal Allows Arbitrary File Overwrite and Modification

Content
View full analysis

Vulnerability Details

File Location: scripts/add_branch.py, lines 12-48
Vulnerability Type: Path traversal and unrestricted filesystem write
Risk Level: High

Vulnerable Code

python
base_path = "/root/.openclaw/workspace/memory"

if type == "domain":
    # Create a new domain file
    file_path = f"{base_path}/domains/{name.lower()}.md"
    content = f"# 🌐 DOMAIN: {name.capitalize()}\n\nDetails about {name}.\n\n---\n*Back to Root:* `MEMORY.md`"
    link_line = f"\n- **[{name.capitalize()}]** -> `memory/domains/{name.lower()}.md`"
    root_file = "/root/.openclaw/workspace/MEMORY.md"
    
    # Create directory if it doesn't exist
    os.makedirs(os.path.dirname(file_path), exist_ok=True)
    # Write the new markdown file
    with open(file_path, "w") as f:
        f.write(content)
        
    # Append a link to the root memory map
    with open(root_file, "a") as f:
        f.write(link_line)
        
elif type == "project":
    # Create a new project file
    file_path = f"{base_path}/projects/{name.lower()}.md"
    content = f"# 🏗️ PROJECT: {name.capitalize()}\n\nStatus and details for {name}.\n\n---\n*Back to Domain:* `{parent_file}`"
    link_line = f"\n1. **[{name.capitalize()}]** -> `memory/projects/{name.lower()}.md`"
    
    # Create directory if it doesn't exist
    os.makedirs(os.path.dirname(file_path), exist_ok=True)
    # Write the new markdown file
    with open(file_path, "w") as f:
        f.write(content)
        
    # If a parent domain file is specified, append a link to it
    if parent_file:
        full_parent_path = f"/root/.openclaw/workspace/{parent_file}"
        if os.path.exists(full_parent_path):
            with open(full_parent_path, "a") as f:
                f.write(link_line)

Technical Analysis

The command-line arguments name and parent_file are incorporated directly into filesystem paths without ...[truncated 2960 chars]

Remediation
View remediation

Remediation Suggestions

  1. Restrict branch names to a safe filename grammar. For example, accept only ASCII letters, digits, underscores, and hyphens:

    python
    import re
    
    if not re.fullmatch(r"[A-Za-z0-9_-]+", name):
        raise ValueError("Branch name contains unsupported characters")
    
  2. Build and resolve paths with pathlib.Path, then verify that the resolved result remains under its designated base directory:

    python
    from pathlib import Path
    
    branch_root = Path(base_path, "domains").resolve()
    file_path = (branch_root / f"{name.lower()}.md").resolve()
    
    try:
        file_path.relative_to(branch_root)
    except ValueError:
        raise ValueError("Branch path escapes the permitted directory")
    
  3. Apply an equivalent containment check to project paths.

  4. Do not accept arbitrary workspace-relative parent paths. Resolve parents exclusively beneath the known domain directory:

    python
    domain_root = Path(base_path, "domains").resolve()
    parent_path = (domain_root / parent_file).resolve()
    
    try:
        parent_path.relative_to(domain_root)
    except ValueError:
        raise ValueError("Parent must be inside memory/domains")
    
  5. Reject absolute paths, . and .. components, path separators in logical branch names, and parent files that do not have the expected .md extension.

  6. Use exclusive creation mode ("x") when a new branch must not replace an existing file. If replacement is an intended feature, require an explicit overwrite option and perform the same containment validation first.

  7. Consider rejecting symlink targets by inspecting path components and opening files using platform protections such as O_NOFOLLOW where available.

  8. Run the helper under a least-privileged account with write access limited to the intended memory directories rather than relying on root-owned hardcoded paths.

Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (2)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill describes and encourages use of a helper script that creates directories, writes markdown files, and appends links, but the manifest does not declare any explicit tool scope such as permissions or allowed-tools. Even if the stated purpose is benign, undeclared file-write capability weakens transparency and policy enforcement, increasing the chance that an agent may modify local files without clear user awareness or sandbox expectations.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This is a real path-manipulation issue: the script accepts a user-controlled --parent value, prefixes it with the workspace root, and appends content to the resulting path if it exists, without restricting it to the intended memory/domain area. An attacker or misbehaving agent can therefore modify arbitrary existing files under /root/.openclaw/workspace, which exceeds the skill's stated purpose of organizing memory files and can corrupt configuration, prompts, or other trusted workspace content.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.