Back to skill

Security audit

Fractal Memory

Security checks for vulnerabilities and agentic risk

Overview

This memory skill is mostly aligned with its purpose, but it needs review because it persistently stores conversation history, promotes it into future agent context, sends full daily logs to an LLM by default, and schedules an unpackaged script.

Install only if you intentionally want durable agent memory. Before enabling it, remove or audit the update_now.py cron step, decide whether full diary contents may be sent to the configured LLM provider, consider disabling USE_LLM or adding redaction, back up memory files, and treat all stored memory as untrusted data until reviewed before it is promoted into MEMORY.md.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (5)

T02 · Agent Memory Poisoning

Error
Location
scripts/rollup-monthly.py:48
Finding

Untrusted diary content can poison persistent agent memory

Content
View full analysis

Vulnerability Details

File Locations:

  • scripts/append_to_daily.py:29-43
  • scripts/rollup-daily.py:68-108
  • scripts/rollup-daily.py:166-186
  • scripts/rollup-weekly.py:62-78
  • scripts/rollup-weekly.py:91-109
  • scripts/rollup-monthly.py:48-74
  • scripts/rollup-monthly.py:80-95
  • SKILL.md:54-65

Vulnerability Type: Persistent memory poisoning through unsanitized content promotion
Risk Level: High

Vulnerable Code

scripts/append_to_daily.py:29-43:

python
daily_dir = DIARY_ROOT / year / "daily"
daily_dir.mkdir(parents=True, exist_ok=True)

today_path = daily_dir / f"{date}.md"

# Create file if it doesn't exist
if not today_path.exists():
    weekday = now.strftime("%A")
    today_path.write_text(f"# {date} ({weekday})\n\n", encoding="utf-8")

# Append event
event = f"\n## {time_str} - {title}\n"
if details:
    event += f"{details}\n"

with open(today_path, "a", encoding="utf-8") as f:
    f.write(event)

scripts/rollup-daily.py:101-108:

python
# Call OpenClaw's LLM via subprocess
result = subprocess.run(
    ['openclaw', 'ask', '--model', LLM_MODEL, '--'],
    input=prompt,
    capture_output=True,
    text=True,
    timeout=30
)

The prompt passed above embeds the entire diary through the following interpolation at scripts/rollup-daily.py:73-75:

python
**Original log:**
{content}

scripts/rollup-weekly.py:62-78:

python
for line in lines:
    line = line.strip()
    if not line or line.startswith('#'):
        continue

    # Extract milestones
    if any(marker in line.lower() for marker in ['created', 'implemented', 'completed', 'launched', 'published']):
        milestones.append(line)
    # Extract themes
    elif any(marker in line.lower() for marker in ['learned', 'discovered', 'realized', 'understood']):
        themes.append(line)

result = []
if themes:
    result.append
...[truncated 3425 chars]
Remediation
View remediation

Remediation Suggestions

  1. Treat all diary entries and rollup summaries as untrusted data.
  2. Store events in a structured format with separate fields for content, source identity, creation time, trust level, and approval status.
  3. Explicitly instruct the summarization model that log contents are quoted data and that instructions found inside them must never be followed.
  4. Enforce an output schema that permits factual summaries but rejects commands, policy statements, tool instructions, and behavioral directives.
  5. Add detection for prompt-injection phrases and suspicious imperative language.
  6. Require explicit human approval before any text is promoted to MEMORY.md.
  7. Preserve source references for every promoted item so it can be traced to its original event.
  8. Load memory through a data-only channel rather than presenting it as authoritative session instructions.
  9. Add regression tests using malicious diary entries to verify that instructions cannot propagate into core memory.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/rollup-daily.py:25
Finding

Complete diary contents are submitted to an external LLM without privacy controls

Content
View full analysis

Vulnerability Details

File Location: scripts/rollup-daily.py:25-26,68-108
Vulnerability Type: Uncontrolled disclosure of potentially sensitive memory data
Risk Level: Medium

Vulnerable Code

python
# LLM Configuration
USE_LLM = True  # Set to False to use heuristic extraction
LLM_MODEL = "deepseek"  # Fast and cheap for summarization

The prompt constructed by extract_summary_llm contains the complete value of content:

python
prompt = f"""Memory summarization request.

**Date:** {date.strftime('%Y-%m-%d (%A)')}

**Original log:**
{content}
"""

The complete prompt is then submitted through OpenClaw:

python
result = subprocess.run(
    ['openclaw', 'ask', '--model', LLM_MODEL, '--'],
    input=prompt,
    capture_output=True,
    text=True,
    timeout=30
)

Technical Analysis

LLM processing is enabled by default. The script reads the entire daily diary and passes it to the configured deepseek model through openclaw ask. No redaction, secret detection, data classification, content minimization, provider-consent check, or local-only mode is applied before submission.

Daily memory may contain personal information, private conversations, internal project details, credentials accidentally recorded by an agent, API values, or other sensitive operational data. The primary documentation describes automated compression but does not clearly disclose that full diary contents may be processed by the configured model provider.

Attack Path

  1. Sensitive information is recorded in the daily diary during normal agent operation.
  2. The scheduled daily rollup reads the entire diary file.
  3. extract_summary_llm interpolates the complete diary into the prompt.
  4. subprocess.run submits that prompt through openclaw ask --model deepseek.
  5. The data leaves the local summarization boundary and becomes subject to the configured provider’s process ...[truncated 370 chars]
Remediation
View remediation

Remediation Suggestions

  1. Disable remote LLM processing by default and require explicit opt-in.
  2. Clearly disclose the selected model, provider boundary, transmitted fields, and relevant retention implications.
  3. Add secret scanning and personal-data redaction before constructing the prompt.
  4. Minimize submitted content to the specific entries required for summarization.
  5. Support a local model or heuristic-only mode as the secure default.
  6. Allow administrators to configure an approved model rather than hard-coding one.
  7. Block submission when content matches credentials, private keys, access tokens, or other restricted classifications.
  8. Record an auditable event whenever diary data is submitted to a model service.

T06 · System Persistence

Warning
Location
references/cron-setup.md:18
Finding

Daily scheduled task executes an absent and unaudited workspace script

Content
View full analysis

Vulnerability Details

File Location: references/cron-setup.md:18-36
Vulnerability Type: Persistent execution of code outside the reviewed Skill package
Risk Level: Medium

Vulnerable Code

javascript
{
  "name": "Daily Memory Rollup",
  "schedule": {
    "kind": "cron",
    "expr": "59 23 * * *",
    "tz": "Asia/Shanghai"
  },
  "sessionTarget": "isolated",
  "wakeMode": "next-heartbeat",
  "payload": {
    "kind": "agentTurn",
    "message": "Execute daily memory rollup: cd ~/.openclaw/workspace && python3 scripts/rollup-daily.py && python3 scripts/update_now.py. This compresses today's diary entry into this week's summary. Log the result.",
    "timeoutSeconds": 90
  },
  "delivery": {
    "mode": "none"
  },
  "enabled": true
}

Technical Analysis

The recommended cron payload executes scripts/update_now.py after the daily rollup. That file is not present in the audited project directory and is not documented as a required component of the memory rollup implementation.

Consequently, the effective scheduled payload depends on mutable code already present or later created in the user’s workspace. The cron job is enabled and runs every day, creating a persistent execution mechanism for a script whose contents are outside the reviewed Skill package. The use of a relative workspace path also means the executed file is not pinned to a verified artifact.

Attack Path

  1. The user follows the cron setup guide and enables the daily job.
  2. An attacker or another untrusted component creates or replaces ~/.openclaw/workspace/scripts/update_now.py.
  3. At the next scheduled run, the agent executes rollup-daily.py.
  4. If that script succeeds, the chained command executes the attacker-controlled update_now.py.
  5. The payload repeats on subsequent scheduled runs until the job or file is removed.

Impact Assessment

The unaudited script exec ...[truncated 404 chars]

Remediation
View remediation

Remediation Suggestions

  1. Remove scripts/update_now.py from the cron command unless it is required.
  2. If required, include the script in the package and subject it to the same audit.
  3. Execute only absolute paths to files installed from the reviewed package.
  4. Verify file ownership, permissions, and a cryptographic digest before execution.
  5. Avoid chaining unrelated scripts in a single scheduled command.
  6. Run scheduled tasks with a restricted service account and a minimal environment.
  7. Configure cron delivery or alerting so unexpected execution is visible.
  8. Document every executable invoked by persistent jobs.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/verify_memory_integrity.py:19
Finding

Integrity verification uses a mutable unauthenticated baseline and omits core memory

Content
View full analysis

Vulnerability Details

File Location: scripts/verify_memory_integrity.py:19-20,41-50,52-82,108-122,207-214
Vulnerability Type: Ineffective integrity and provenance validation
Risk Level: Medium

Vulnerable Code

python
WORKSPACE = Path.home() / ".openclaw" / "workspace"
MEMORY_DIR = WORKSPACE / "memory"
INTEGRITY_FILE = MEMORY_DIR / "integrity.json"

Only files beneath MEMORY_DIR are scanned:

python
def scan_memory_files():
    """Scan all memory files and calculate checksums"""
    files = {}

    # Scan diary files
    for md_file in MEMORY_DIR.rglob("*.md"):
        if md_file.is_file():
            rel_path = str(md_file.relative_to(WORKSPACE))
            checksum = calculate_checksum(md_file)

            if checksum:
                files[rel_path] = {
                    "checksum": checksum,
                    "size": md_file.stat().st_size,
                    "modified": datetime.fromtimestamp(md_file.stat().st_mtime).isoformat()
                }

    # Scan JSON state files
    for json_file in MEMORY_DIR.glob("*.json"):
        if json_file.name != "integrity.json" and json_file.is_file():
            rel_path = str(json_file.relative_to(WORKSPACE))
            checksum = calculate_checksum(json_file)

            if checksum:
                files[rel_path] = {
                    "checksum": checksum,
                    "size": json_file.stat().st_size,
                    "modified": datetime.fromtimestamp(json_file.stat().st_mtime).isoformat()
                }

    return files

Expected-pattern filtering excludes all diary modifications from most anomaly analysis:

python
expected_patterns = [
    "memory/diary/",  # Daily/weekly/monthly rollups
    "memory/rollup-state.json",  # Rollup state
    "memory/entities/",  # Knowledge graph updates
]

unexpected_mods = [
    mod for mod in changes["modified"]
   
...[truncated 2046 chars]
Remediation
View remediation

Remediation Suggestions

  1. Include root-level MEMORY.md and every other session-loaded memory file in the integrity inventory.
  2. Authenticate the baseline with an HMAC or digital signature whose key is stored outside the writable workspace.
  3. Store verification records in an append-only or separately protected location.
  4. Do not automatically trust and overwrite the baseline after detecting changes.
  5. Require approval before accepting unexpected modifications as the new baseline.
  6. Record authenticated writer identity and source-event references for every memory update.
  7. Inspect diary changes for suspicious content instead of excluding the entire directory.
  8. Fail safely when the baseline is missing, malformed, or unexpectedly replaced.
  9. Send integrity alerts to a channel that a workspace attacker cannot silently modify.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/append_to_daily.py:11
Finding

Helper scripts use a hard-coded developer-specific workspace path

Content
View full analysis

Vulnerability Details

File Locations:

  • scripts/append_to_daily.py:11-12
  • scripts/ensure_daily_log.py:12-14

Vulnerability Type: Unsafe and non-portable filesystem configuration
Risk Level: Low

Vulnerable Code

scripts/append_to_daily.py:11-12:

python
WORKSPACE = Path("/Users/brianq/.openclaw/workspace")
DIARY_ROOT = WORKSPACE / "memory/diary"

scripts/ensure_daily_log.py:12-14:

python
WORKSPACE = Path("/Users/brianq/.openclaw/workspace")
DIARY_ROOT = WORKSPACE / "memory/diary"
STATE_FILE = WORKSPACE / "memory/heartbeat-state.json"

Technical Analysis

These helpers write to an absolute path associated with a specific developer account rather than deriving the active user’s workspace or accepting an explicit configuration value. This differs from the rollup scripts, which use Path.home().

On most other systems the scripts will fail, but on a shared system where the hard-coded path exists and is writable, the helpers may write memory events or modify heartbeat state in another user’s workspace. Inconsistent workspace selection can also cause the writer and rollup components to operate on different memory trees.

Attack Path

  1. The Skill is installed or invoked under an account other than the hard-coded user.
  2. The script resolves its output to /Users/brianq/.openclaw/workspace rather than the caller’s workspace.
  3. If the target path is writable, diary entries or heartbeat state are created or modified there.
  4. Rollup scripts using the current account’s home directory may process a different workspace, causing unintended cross-user modification or loss of expected records.

Impact Assessment

No privilege escalation is created by the path alone; normal filesystem permissions still apply. Where permissions permit, the issue can cause unauthorized modification of another workspace’s diary and state files. Otherwise, it primarily causes availability a ...[truncated 22 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace the hard-coded path with Path.home() / ".openclaw" / "workspace".
  2. Prefer an explicit workspace argument or validated environment variable.
  3. Resolve and validate the final path before writing.
  4. Confirm that the workspace is owned by the current user and reject unsafe ownership or permissions.
  5. Use one shared configuration module across all scripts so every component operates on the same workspace.
  6. Add tests covering multiple user-home and workspace configurations.
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
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (22)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

This finding is significant to the extent it indicates undeclared integrity monitoring, tamper detection, checksum tracking, or anomaly detection behaviors. Such features can read broadly across user memory files and potentially collect metadata not disclosed to the user, which is especially sensitive in a persistent conversation logging system.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This finding is significant to the extent it indicates undeclared integrity monitoring, tamper detection, checksum tracking, or anomaly detection behaviors. Such features can read broadly across user memory files and potentially collect metadata not disclosed to the user, which is especially sensitive in a persistent conversation logging system.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

This finding is significant to the extent it indicates undeclared integrity monitoring, tamper detection, checksum tracking, or anomaly detection behaviors. Such features can read broadly across user memory files and potentially collect metadata not disclosed to the user, which is especially sensitive in a persistent conversation logging system.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

This finding is significant to the extent it indicates undeclared integrity monitoring, tamper detection, checksum tracking, or anomaly detection behaviors. Such features can read broadly across user memory files and potentially collect metadata not disclosed to the user, which is especially sensitive in a persistent conversation logging system.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

This finding is significant to the extent it indicates undeclared integrity monitoring, tamper detection, checksum tracking, or anomaly detection behaviors. Such features can read broadly across user memory files and potentially collect metadata not disclosed to the user, which is especially sensitive in a persistent conversation logging system.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

This finding is significant to the extent it indicates undeclared integrity monitoring, tamper detection, checksum tracking, or anomaly detection behaviors. Such features can read broadly across user memory files and potentially collect metadata not disclosed to the user, which is especially sensitive in a persistent conversation logging system.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding

The skill clearly instructs file creation, file copying, permission changes, and execution of Python scripts, yet it declares no explicit tool scope or permissions. This is dangerous because it hides the actual capability footprint from users and policy layers, increasing the risk of unintended file modification or shell execution without informed approval.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The skill sets up persistent session state and diary storage, which expands the security and privacy boundary beyond the active session. This is risky because stored memory can outlive user expectations, be consumed by later sessions, and become a durable repository of sensitive or attacker-influenced content.

Content

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

1. Set Up Directory Structure

bash
mkdir -p memory/diary/{2026/{daily,weekly,monthly},sticky-notes/{workflows,apis,commands,facts}}

2. Initialize State Files

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

Documenting cron-based rollups without clearly warning that they run unattended and modify files on a schedule can lead to unexpected background changes and persistent storage growth. In a memory tool, unattended summarization increases the chance that sensitive content is processed or retained without the user's immediate awareness.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill instructs users to persistently log conversation content and compress it into long-term memory without a clear privacy warning, consent model, or retention boundaries. This is dangerous because sensitive prompts, credentials, personal data, or proprietary information may be silently retained across sessions and surfaced later in broader contexts.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The instructions explicitly encourage comprehensive logging of conversational content into persistent files. In the context of an agent memory system, this creates a substantial data minimization and confidentiality risk because secrets, personal data, and sensitive operational context can accumulate and later be exposed, misused, or improperly summarized.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The architecture explicitly instructs the agent to write conversation content to persistent memory immediately, but it does not require user consent, data minimization, or filtering of secrets and sensitive information before storage. In a memory-management skill, this increases the chance that credentials, personal data, proprietary prompts, or other sensitive session content will be retained on disk and later resurfaced through context loading or rollups.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The guide instructs users to create recurring cron jobs that automatically run rollup scripts against persistent memory files, but it does not clearly warn that these jobs will continue modifying stored memory without further confirmation. In a memory-management skill, that omission is security-relevant because users may enable unattended background changes to long-term context, increasing risk of unintended data loss, corruption, or silent propagation of bad summaries.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
82% confidence
Finding

The cron examples configure persistent scheduled agent turns that execute file-modifying commands in an isolated session on a recurring basis. Although the feature is central to this skill's purpose, unattended session persistence increases the blast radius of mistakes or compromised scripts because modifications happen automatically over time and may not be immediately visible to the user.

Content

Scanner excerpt · references/cron-setup.md (reported line 14)May include surrounding context.

md
## Setting Up Cron Jobs

Use the `cron` tool to create these jobs:

### 1. Daily Rollup

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The prompt text instructs the model entirely in Chinese and requires a specific output format in Chinese, which imposes a language choice on the summarization behavior. The file does not provide any user opt-in, configuration, or documented justification for this locale constraint.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The script forwards full diary content to openclaw ask, which may send sensitive personal data to an external model or service. For a memory-rollup skill, this meaningfully expands data exposure beyond local file processing and can leak private notes, credentials, or confidential project details without clear disclosure or consent.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/rollup-daily.py (reported line 102)May include surrounding context.

python
try:
        # Call OpenClaw's LLM via subprocess
        result = subprocess.run(
            ['openclaw', 'ask', '--model', LLM_MODEL, '--'],
            input=prompt,
            capture_output=True,

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

A memory rollup skill is expected to read, summarize, and write memory files, but spawning an external command-line tool is a broader execution capability than necessary for the stated purpose. Even if used for summarization, the manifest does not explicitly justify shelling out to another program rather than performing local processing within the skill.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
87% confidence
Finding

This code performs a file write to a long-term memory document, modifying user data on disk. Although the script logs that MEMORY.md was updated afterward, there is no prior confirmation prompt or explicit warning at the point of execution that the file will be changed automatically, including when run via cron.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
55% 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 · scripts/verify_memory_integrity.py (reported line 169)May include surrounding context.

python
print("🔒 Memory Integrity Verification - Fractal Memory System")
    print("=" * 60)
    
    # Load previous state
    old_state = load_integrity_state()
    last_check = old_state.get("last_check")

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The guide instructs users to move existing memory files with mv in a loop, which can irreversibly alter the current layout if the pattern matches unexpectedly or if the migration is interrupted. Although the document later mentions backups in the Tips section, there is no explicit warning immediately before the destructive migration step, increasing the chance of accidental data loss during execution.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
79% confidence
Finding

The code creates or updates a persistent state file on disk to track processing history. While this is operationally useful, there is no clear warning in the script header or usage text that running the script will modify rollup-state.json.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.