Back to skill

Security audit

Save

Security checks for vulnerabilities and agentic risk

Overview

This local memory skill is not clearly malicious, but it can persist and index more local content than users may expect, including files marked “off the record” after a later rebuild.

Review before installing. Use this only if you want long-term local memory and are comfortable with workspace Markdown being indexed and summarized into local files. Do not rely on “off the record” for privacy in this version; avoid saving secrets or sensitive conversations unless the indexer is restricted to an approved directory and generated indexes can be deleted or rebuilt safely.

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

T09 · Insecure Skill Coding Practices

Warning
Location
memory-index.py:40
Finding

Overbroad Workspace Indexing Exposes Sensitive and Untrusted Markdown Content

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
memory-index.py:40
Finding

Off-the-Record Conversations Are Indexed During Subsequent Rebuilds

Content
View full analysis
50KB)** — write a summary/executive brief instead of full content - **"Save this as [custom name]"** — use the custom name as filename ``` ```python def get_md_files(): """Get all knowledge files: workspace .md + saved conversations .md/.txt.""" files = [] for root, dirs, fnames in os.walk(WORKSPACE): if "node_modules" in root or ".git" in root: continue for f in fnames: if f.endswith(".md"): files.append(os.path.join(root, f)) # Also index saved conversations convos_dir = SAVED_DIR if os.path.isdir(convos_dir): for f in os.listdir(convos_dir): if f.endswith(".md") or f.endswith(".txt"): files.append(os.path.join(convos_dir, f)) return sorted(files) ``` ### Technical Analysis The documented off-the-record workflow writes the conversation file but merely skips the immediate log update and index rebuild. There is no persistent exclusion marker, denylist, metadata field, or separate non-indexed storage location. Because the file remains in `SAVED_CONVERSATIONS_DIR`, every later call to `get_md_files()` selects it based solely on its `.md` or `.txt` extension. The workspace-wide recursive scan can also select the same saved Markdown file before the explicit saved-directory scan. A later normal save or manual rebuild therefore defeats the user's stated privacy choice. ### Attack Path 1. A user requests that a conversation be saved with “do not index it” or “off the record ...[truncated 1009 chars]
Remediation
View remediation
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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (20)

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

The documented purpose is narrowly framed as saving conversations, but the described behavior expands into indexing general workspace markdown, search, tag extraction, JSON/topic-map generation, and grep fallback. This mismatch is dangerous because users may authorize a memory-save feature without realizing it also scans and indexes unrelated workspace content, potentially broadening data exposure and persistence.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The 'off the record' guidance is internally contradictory: it still writes the conversation to disk while merely skipping logging and indexing. This is dangerous because users asking not to record content would still have persistent copies created, defeating privacy expectations and potentially exposing sensitive material through direct filesystem access or backups.

Content

No source excerpt is available for this finding.

Direct flow: os.environ.get (credential/environment) → subprocess.run (code execution)

High
Category
Data Flow
Confidence
80% confidence
Finding

Data flows directly from a source (env vars, files, network) to a sink (network output, exec, file write) without intermediate validation.

Content

Scanner excerpt · memory-index.py (reported line 352)May include surrounding context.

python
# Fallback: try grep
            print("No FTS5 matches. Trying grep fallback...")
            import subprocess
            result = subprocess.run(
                ["grep", "-rl", "-m5", query, WORKSPACE],
                capture_output=True, text=True,
                env={"HOME": os.environ.get("HOME", os.path.expanduser("~"))}

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding

The skill requires shell execution plus file read/write and environment access, but it does not declare any explicit tool scope or permission boundaries. That makes the effective capability surface broader and less auditable, increasing the chance the agent can execute persistence and indexing actions without clear user or platform controls.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
83% confidence
Finding

The setup and init actions create persistent storage and initialize a conversation log automatically during installation. While not inherently malicious, automatic session-persistence setup increases the chance that later interactions are retained without users appreciating that the environment has been prepared for long-term storage.

Content

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

md
install:
      - id: setup
        kind: setup
        label: "Create saved conversations directory"
        run: "mkdir -p ~/.openclaw/workspace/saved"
      - id: init-log
        kind: init

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill promotes saving and indexing conversations but does not prominently warn that potentially sensitive session content will be written to long-term local storage and made searchable. Users may reasonably assume ephemeral handling, so the missing disclosure undermines informed consent and increases privacy and data-retention risk.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Broad trigger phrases like 'save this' or 'save this conversation' overlap with normal conversational language and can cause unintended invocation. In a persistence skill, accidental activation is risky because it may store sensitive session content to disk and trigger indexing without sufficiently clear consent.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill explicitly instructs the agent to persist conversation-derived summaries and user-provided material to durable local storage. Even if intended as a memory feature, this creates a real confidentiality risk because sensitive data from the session can be retained beyond the user's expectation and later discovered through search or file access.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

Saying the agent handles '/save' automatically without clearly bounded invocation rules creates ambiguity about when the skill may execute. That ambiguity is especially risky for a state-changing skill because automatic persistence and index rebuilds can occur from casual language or inferred intent rather than explicit user authorization.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
80% confidence
Finding

The first-time setup instructions normalize creation of a persistent saved-conversation store and log file, reinforcing long-term retention as a default behavior. In a skill designed to handle session-derived content, that persistence context makes accidental or overbroad storage more likely and increases privacy impact.

Content

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

md
#    - Python 3.8+ (stdlib only — no pip packages needed)
#    - An OpenClaw agent with write/edit/exec/read tools

# 1. Create the saved conversations directory (inside the workspace)
mkdir -p ~/.openclaw/workspace/saved

# 2. Initialize the conversation log

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The module docstring describes a memory search/index tool, contradicting the manifest's save-focused purpose. This mismatch is security-relevant because reviewers and users may grant permissions based on the manifest while the code signals a broader retrieval and indexing role with greater access to local data.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill is presented as a save-to-memory utility, but the implementation walks the broader workspace and indexes arbitrary Markdown and text files. That capability expansion increases exposure because users and reviewers may authorize a seemingly narrow persistence skill while it actually performs generalized data collection over local content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The code writes a topic-index JSON derived from workspace and saved-conversation content without explicit disclosure or consent. That creates a persistent, easily searchable summary of user-derived data, which can increase privacy exposure even if the original files were less discoverable.

Content

No source excerpt is available for this finding.

Tainted flow: 'TOPIC_MAP_PATH' from os.environ.get (line 144, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
87% confidence
Finding

TOPIC_MAP_PATH is derived from an environment-controlled directory and is opened for write without validation. If an attacker can influence the environment for this skill, they can redirect writes to arbitrary filesystem locations writable by the process, causing unauthorized file creation or overwrite and potential leakage of indexed metadata.

Content

Scanner excerpt · memory-index.py (reported line 191)May include surrounding context.

python
})
    
    os.makedirs(os.path.dirname(TOPIC_MAP_PATH), exist_ok=True)
    with open(TOPIC_MAP_PATH, 'w') as f:
        json.dump(topic_map, f, indent=1)
    
    map_size = os.path.getsize(TOPIC_MAP_PATH)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The stub index persists snippets and headings from indexed files to disk without warning, potentially exposing conversation fragments and other sensitive text in a consolidated file. In a memory-saving skill, undisclosed persistence of summarized content is especially risky because it changes the visibility and accessibility of user data.

Content

No source excerpt is available for this finding.

Tainted flow: 'STUB_PATH' from os.environ.get (line 22, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
89% confidence
Finding

STUB_PATH is built from an environment-derived base path and then written without any path validation. An attacker controlling that environment variable can redirect the stub output to unintended locations, potentially overwriting files or planting content that exposes indexed conversation snippets.

Content

Scanner excerpt · memory-index.py (reported line 238)May include surrounding context.

python
cleaned.append(line)
    
    os.makedirs(os.path.dirname(STUB_PATH), exist_ok=True)
    with open(STUB_PATH, 'w') as f:
        f.write('\n'.join(cleaned))
    
    stub_size = len('\n'.join(cleaned).encode('utf-8'))

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Spawning external grep adds an undeclared filesystem search capability not justified by a save-oriented skill. In context, this is more dangerous because it bypasses the indexed subset and performs direct recursive content inspection of the workspace, which can reveal data the user did not expect this skill to scan.

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 · memory-index.py (reported line 352)May include surrounding context.

python
# Fallback: try grep
            print("No FTS5 matches. Trying grep fallback...")
            import subprocess
            result = subprocess.run(
                ["grep", "-rl", "-m5", query, WORKSPACE],
                capture_output=True, text=True,
                env={"HOME": os.environ.get("HOME", os.path.expanduser("~"))}

Tainted flow: 'WORKSPACE' from os.environ.get (line 17, credential/environment) → subprocess.run (code execution)

Medium
Category
Data Flow
Confidence
81% confidence
Finding

WORKSPACE comes from the environment and is passed to grep as the search root without validation. In this skill's context, that broadens the tool from searching expected memory data to recursively reading arbitrary accessible directories, which can expose sensitive files or create an unintended capability for filesystem reconnaissance.

Content

Scanner excerpt · memory-index.py (reported line 352)May include surrounding context.

python
# Fallback: try grep
            print("No FTS5 matches. Trying grep fallback...")
            import subprocess
            result = subprocess.run(
                ["grep", "-rl", "-m5", query, WORKSPACE],
                capture_output=True, text=True,
                env={"HOME": os.environ.get("HOME", os.path.expanduser("~"))}

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

Topic-map and tag-generation features extend the skill beyond simple conversation saving and create additional derived-data artifacts on disk. While not inherently malicious, undisclosed metadata extraction increases privacy risk and can make sensitive themes easier to enumerate than the raw files themselves.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.