Back to skill

Security audit

Automated daily memory backfill for OpenClaw sessions

Security checks for vulnerabilities and agentic risk

Overview

This skill is purpose-aligned but needs review because it reads private OpenClaw session history and can write or automate persistent agent memory, including LLM-generated summaries.

Install only if you are comfortable letting the skill read your OpenClaw session logs and create or update memory files from them. Prefer dry-run and simple extraction first, review generated memory before relying on it, avoid unattended cron until you trust the output, and use OpenAI or Anthropic backends only when the session content is acceptable to send to those providers.

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
memory_sync.py:1481
Finding

Untrusted Session Content Can Poison Persistent Agent Memory

Content
View full analysis

Vulnerability Details

File Location: memory_sync.py:1481-1495, memory_sync.py:1522-1547, memory_sync.py:1567-1591, memory_sync.py:1646-1655, and memory_sync.py:1797-1839
Vulnerability Type: Indirect prompt injection leading to persistent memory poisoning
Risk Level: High

Vulnerable Code

python
def prepare_conversation_text(messages: list[Message], max_chars: int = 100000) -> str:
    """Prepare conversation text for summarization."""
    lines = []
    total_chars = 0

    for msg in messages:
        sanitized_content = sanitize_content(msg.text_content)

        time_str = msg.timestamp.strftime('%H:%M')
        role = msg.role.upper()
        model_str = f" [{msg.model}]" if msg.model else ""

        line = f"[{time_str}] {role}{model_str}: {sanitized_content[:500]}"

        if total_chars + len(line) > max_chars:
            break

        lines.append(line)
        total_chars += len(line)

    return '\n\n'.join(lines)
python
def _build_summarization_prompt(
    log_date: date,
    messages: list[Message],
    transitions: list[ModelTransition],
    existing_content: Optional[str] = None
) -> str:
    """Build the prompt for LLM summarization."""
    conversation_text = prepare_conversation_text(messages)
    transitions_note = format_transitions_note(transitions)

    day_name = log_date.strftime('%A, %Y-%m-%d')

    user_prompt = f"""Generate a daily memory summary for {day_name}.

Conversation log:
{conversation_text}
{transitions_note}

Remember: Focus on accomplishments, decisions, insights, and context. Be concise and narrative."""

    if existing_content:
        _, hand_written = extract_preserved_content(existing_content)
        if hand_written:
            user_prompt += f"\n\nExisting hand-written notes (PRESERVE AND INCORPORATE):\n{hand_written}"

    return user_prompt
python
user_prompt = _build_summarization_prompt(
    log_date, messages, transitions, existing_content
)

full_prompt = f
...[truncated 4492 chars]
Remediation
View remediation

Remediation Suggestions

  1. Establish an explicit trust boundary in the system prompt. State that all conversation-log and preserved-note content is untrusted quoted data and that instructions found inside it must never be followed.

  2. Use strong structural delimiters. Serialize each message as structured JSON with clearly separated metadata and content fields rather than interpolating raw text into a free-form prompt. Explain that delimited content is evidence to summarize, not an instruction source.

  3. Constrain model output. Require a strict schema containing only allowed summary fields, such as accomplishments, decisions, insights, and follow-ups. Parse and validate the response before writing it.

  4. Reject suspicious persistent directives. Add output checks for imperative instructions, attempts to alter future Agent behavior, unrelated policy statements, and content unsupported by the source conversation.

  5. Require approval for active memory writes. Write LLM-generated summaries to a staging location and require human confirmation before promoting them into the Agent's active memory directory, especially for unattended scheduled runs.

  6. Preserve provenance. Mark each generated claim with source-message identifiers or maintain a separate provenance record so future consumers can distinguish generated summaries from user-authored trusted memory.

  7. Use defense-in-depth validation. Continue secret sanitization, but supplement it with prompt-injection detection and semantic output validation. Secret filtering alone does not mitigate instruction injection.

  8. Add adversarial tests. Include conversation messages that say, for example, to ignore prior instructions, create permanent rules, conceal content, or fabricate accomplishments. Verify that none of those instructions appear as authoritative memory.

  9. Minimize downstream trust. Configure future Agent sessions to treat auto-generated memory as untrusted reference m ...[truncated 49 chars]

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 (19)

Context Leakage

High
Category
Data Exfiltration
Confidence
91% confidence
Finding

The skill's core purpose is to extract conversations from session logs and reconstruct memory, which inherently concentrates potentially sensitive context in a new artifact and may pass that context into summarization flows. Even with sanitization claims, this increases exposure surface because secrets, private discussions, and sensitive operational history may be copied, retained longer, or sent to a model backend.

Content

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

md
| `backfill --since YYYY-MM-DD` | Backfill from date to present |
| `backfill --all` | Backfill all missing dates |
| `backfill --incremental` | Backfill only changed dates since last run |
| `extract` | Extract conversations matching criteria |
| `summarize --date YYYY-MM-DD` | Generate LLM summary for a single day |
| `transitions` | List model transitions |
| `validate` | Check memory files for consistency issues |

External Model or Provider Selection

High
Category
Excessive Agency
Confidence
90% confidence
Finding

Allowing arbitrary external model selection for summarization can route sensitive memory content to different providers or models with varying privacy, retention, and regional handling guarantees. Without policy controls or warnings, users may unknowingly send reconstructed session history to a third party that is not approved for that data class.

Content

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

memory-sync backfill --today --summarize --summarize-backend openai

Override model for any backend

memory-sync backfill --today --summarize --model claude-sonnet-4-20250514 memory-sync backfill --today --summarize --summarize-backend openai --model gpt-4o

text

External Model or Provider Selection

High
Category
Excessive Agency
Confidence
90% confidence
Finding

This example explicitly routes summarization to OpenAI with a chosen model, which implies external transmission of memory-derived content and increases the chance of policy violations or accidental data export. The danger is amplified by the skill's function of reconstructing broad historical session context, which may be more sensitive than a narrow prompt.

Content

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

Override model for any backend

memory-sync backfill --today --summarize --model claude-sonnet-4-20250514 memory-sync backfill --today --summarize --summarize-backend openai --model gpt-4o

text

The `openclaw` backend is recommended as it:

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

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

md
**Additional flags:**
- `--dry-run` - Show what would be created without creating files
- `--force` - Overwrite existing files (required for regeneration)
- `--preserve` - Keep hand-written content when regenerating
- `--summarize` - Use LLM for narrative summaries
- `--summarize-backend BACKEND` - Backend for summarization: `openclaw` (default), `anthropic`, `openai`

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · memory_sync.py (reported line 1762)May include surrounding context.

python
**Additional flags:**
- `--dry-run` - Show what would be created without creating files
- `--force` - Overwrite existing files (required for regeneration)
- `--preserve` - Keep hand-written content when regenerating
- `--summarize` - Use LLM for narrative summaries
- `--summarize-backend BACKEND` - Backend for summarization: `openclaw` (default), `anthropic`, `openai`

Self-Modification

High
Category
Rogue Agent
Confidence
85% confidence
Finding

Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Content

Scanner excerpt · memory_sync.py (reported line 2064)May include surrounding context.

python
**Additional flags:**
- `--dry-run` - Show what would be created without creating files
- `--force` - Overwrite existing files (required for regeneration)
- `--preserve` - Keep hand-written content when regenerating
- `--summarize` - Use LLM for narrative summaries
- `--summarize-backend BACKEND` - Backend for summarization: `openclaw` (default), `anthropic`, `openai`

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
99% confidence
Finding

Passing env={**os.environ} forwards the entire parent environment to the spawned openclaw subprocess, potentially exposing API keys, tokens, and other secrets unrelated to summarization. If the subprocess, its plugins, or downstream components are compromised or overly permissive, this becomes a broad credential-harvesting path.

Content

Scanner excerpt · memory_sync.py (reported line 1590)May include surrounding context.

python
capture_output=True, 
            text=True, 
            timeout=180,
            env={**os.environ}  # Inherit environment
        )
        if result.returncode == 0:
            # sessions_spawn returns the agent's response

Context Leakage

High
Category
Data Exfiltration
Confidence
95% confidence
Finding

The extract command supports searching and exporting conversation content directly from session logs, which is a strong context-leakage primitive. Although output is sanitized for known secret patterns, it still enables disclosure of sensitive non-secret information such as proprietary discussions, personal data, and operational context.

Content

Scanner excerpt · memory_sync.py (reported line 2271)May include surrounding context.

python
@click.option("--format", "output_format", default="md", type=click.Choice(['md', 'json', 'text']), help="Output format")
@click.option("--sessions-dir", default=None, help="Path to session logs directory")
def extract(target_date, query, model, output_format, sessions_dir):
    """Extract conversations matching criteria."""
    sessions_path = Path(sessions_dir) if sessions_dir else get_default_sessions_dir()

    if not sessions_path.exists():

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill documentation describes capabilities that read session logs, write memory files, invoke shell commands, access environment variables, and optionally call external APIs, but it does not declare any explicit tool scope or allowed-tools/permissions boundary. In an agent ecosystem, missing scope declarations weakens least-privilege controls and makes it easier for the skill to run with broader authority than users may expect.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% 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 · SKILL.md (reported line 33)May include surrounding context.

md
# Run directly from skill directory
python ~/.openclaw/skills/memory-sync/memory_sync.py compare

# Or create an alias for convenience
alias memory-sync="python ~/.openclaw/skills/memory-sync/memory_sync.py"

# Check for gaps

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill advertises direct summarization backends that can send reconstructed memory content to Anthropic or OpenAI, but it does not prominently warn that user conversations and memory data may leave the local system. Because these logs may contain sensitive personal, operational, or credential-adjacent content, omission of an explicit off-system privacy warning creates a real risk of unintentional data disclosure.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The summarization pipeline aggregates broad session contents and preserved handwritten notes into durable memory summaries, creating a persistent natural-language leakage channel. Secret regex filtering does not reliably remove all sensitive facts, so confidential information may be retained or propagated in memory files or outbound prompts.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill delegates summarization to an external openclaw process, sending compiled session logs and preserved notes outside the current process boundary. This creates a real exfiltration and trust-boundary risk, especially because the summarized input is derived from potentially sensitive local logs.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
94% confidence
Finding

The code launches an external openclaw subprocess to summarize session data, which expands the trust boundary and can expose sensitive conversation content to another program with the caller's privileges. While arguments are passed as a list rather than a shell string, this still creates risk because the subprocess inherits environment and operates on untrusted prompt content.

Content

Scanner excerpt · memory_sync.py (reported line 1585)May include surrounding context.

python
cmd.extend(["--model", model])
    
    try:
        result = subprocess.run(
            cmd, 
            capture_output=True, 
            text=True,

External Transmission

Medium
Category
Data Exfiltration
Confidence
96% confidence
Finding

The code is configured to send data to https://api.anthropic.com/v1, meaning local session content is transmitted to an external service. In the context of reconstructing agent memory from logs, this outbound transfer is security-relevant because the data source may contain sensitive conversations and operational details.

Content

Scanner excerpt · memory_sync.py (reported line 1627)May include surrounding context.

python
# Configure based on provider
    if provider == "anthropic":
        api_key = os.environ.get('ANTHROPIC_API_KEY')
        base_url = "https://api.anthropic.com/v1"
        default_model = "claude-sonnet-4-20250514"
        if not api_key:
            raise ValueError(

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The OpenAI/Anthropic backend path transmits session logs and possibly preserved hand-written notes to third-party LLM services, but the CLI does not provide an explicit disclosure or confirmation at the point of use. Even with attempted secret sanitization, narrative content can still contain sensitive business, personal, or operational data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The Anthropic-specific summarization path sends conversation logs to Anthropic without a dedicated disclosure or consent mechanism. Because the source data comes from full session history and optional preserved notes, this can leak sensitive contextual information even if credentials are redacted.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The extract command materially expands the skill from memory reconstruction into general conversation search and export, enabling direct disclosure of session contents in md/json/text formats. In a tool handling agent logs, that broad extraction capability increases privacy and data-leakage risk beyond the stated purpose.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The manifest centers on reconstructing and verifying memory coverage from session logs. The code separately extracts, formats, and exports model transition histories, including a dedicated CLI command and JSON output, which is useful telemetry but not clearly part of the declared memory-sync scope.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.