Back to skill

Security audit

Recall Local

Security checks for vulnerabilities and agentic risk

Overview

This skill is a local memory search tool, but it exposes private agent memory over an unauthenticated network service and installs a persistent background process by default.

Review carefully before installing. Only use this if you are comfortable running a local service that reads your OpenClaw memory files. It should bind to 127.0.0.1, require authentication for any LAN access, avoid returning absolute file paths, reject empty searches, and make LaunchAgent auto-start an explicit optional step with uninstall instructions.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (2)

T06 · System Persistence

Warning
Location
SKILL.md:16
Finding

Persistent User-Level Service Installed Through a macOS LaunchAgent

Content
View full analysis
~/Library/LaunchAgents/ai.wren.recall-local.plist << 'EOF' Labelai.wren.recall-local ProgramArguments /opt/homebrew/bin/node /Users/YOUR_USERNAME/clawd/tools/recall-local/server.js RunAtLoad KeepAlive StandardOutPath/Users/YOUR_USERNAME/clawd/tools/recall-local/recall.log StandardErrorPath/Users/YOUR_USERNAME/clawd/tools/recall-local/recall.log EOF # Replace YOUR_USERNAME, then load it launchctl load ~/Library/LaunchAgents/ai.wren.recall-local.plist ``` ### Technical Analysis The documented setup copies an executable JavaScript file into the user's home directory and registers it as a macOS LaunchAgent. The `RunAtLoad` property starts the process whenever the user logs in, while `KeepAlive` directs `launchd` to restart it after termination. This behavior creates cross-session persistence. Persistent execution is not required for the core function of searching local memory files because the server can be started on demand, as the documentation itself demonstrates. Although the LaunchAgent is installed transparently and runs only with the current user's privileges, making it the default setup exceeds the minimum execution lifetime needed for local search. The persistent service executes the mutabl ...[truncated 1193 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/server.js:8
Finding

Unauthenticated Network Exposure of Private Agent Memory

Content
View full analysis
s.trim()).filter(s => s.length > 20); for (const part of parts) { chunks.push({ text: part, source: path.basename(source || filePath), file: filePath }); } } ``` The search endpoint has no authentication or client-origin restriction and serializes the complete result objects: ```js if (url.pathname === '/search') { const q = url.searchParams.get('q') || ''; // Reload files on each search so it always reflects latest memory reload(); const results = search(memories, q); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ results, total: memories.length })); return; } if (url.pathname === '/reload') { reload(); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify({ ok: true, chunks: memories.length })); return; } ``` The server listens on every available IPv4 network interface: ```js server.listen(PORT, '0.0.0.0', () => { ``` ### Technical Analysis The server indexes potentially sensitive agent-history and working-state files from the user's home directory. It then exposes search results through an HTTP endpoint without authentication, authorization, access tokens, or client-address validation. Binding to `0.0.0.0` makes the servic ...[truncated 2322 chars]
Remediation
View remediation
{ ``` If IPv6 loopback support is required, handle `::1` explicitly rather than listening on all interfaces. 2. Update documentation so it does not imply that a service bound to every interface is localhost-only. 3. If remote or mobile access is an intended feature, require explicit opt-in and implement authentication using a securely generated token. Use TLS through a trusted local reverse proxy or another authenticated encrypted channel. 4. Enforce authorization before serving `/search` or `/reload`. Do not rely solely on the secrecy of the port number. 5. Return an allowlisted response object rather than serializing internal records: ```js const publicResults = results.map(({ text, source, score }) => ({ text, source, score })); res.end(JSON.stringify({ results: publicResults, total: memories.length })); ``` 6. Remove the absolute `file` path from indexed objects if it is not needed: ```js chunks.push({ text: part, source: path.basename(source || filePath) }); ``` 7. Consider rejecting empty searches or returning metadata only, because empty queries currently disclose recent memory content without requiring any knowledge of the archive. 8. Add restrictive response headers, request limits, query-length limits, and rate limiting to reduce browser-based abuse and bulk enumeration. 9. Add automated tests confirming that: - The listener is inaccessible through non-loopback interfaces. - Unauthenticated requests are rejected if remote access is enabled. - API responses never contain absolute filesystem paths. - Empty or abusive queries cannot be used for unrestricted content enumeration. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (16)

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Content

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

Search (agent use)

bash
curl -s "http://localhost:3456/search?q=YOUR+QUERY" | python3 -c "
import json,sys
d = json.load(sys.stdin)
print(f'{d[\"total\"]} chunks indexed')

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill exposes network behavior by instructing the user to run a local HTTP server and query it over localhost, but it does not declare an explicit tool scope such as network permissions. Missing scope disclosure weakens reviewability and can cause agents or users to invoke networking behavior they did not expect.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The description says to use the skill when you need to find 'something from past sessions' or 'anything in the agent's history,' which is extremely broad and overlaps with many ordinary recall tasks. It does not clearly bound when the skill should or should not activate, nor provide negative examples, increasing the chance of unintended invocation.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The document says 'nothing leaves your machine' while also advertising access from other devices on the same local network. If the server binds beyond localhost, memory contents become reachable from other hosts, contradicting the privacy claim and increasing the chance of unintended data exposure.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The setup block performs persistent system changes by creating a LaunchAgent and enabling auto-start, but the markdown does not prominently warn about these side effects. Hidden persistence increases the risk that an operator or agent executes the setup without realizing it installs a background service that survives the current session.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
93% confidence
Finding

This setup creates a macOS LaunchAgent-based persistence mechanism so the server starts automatically on login. Persistence is security-relevant because it keeps a data-serving process running beyond the user's immediate task and increases the window for abuse or accidental exposure.

Content

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

md
cp "$(dirname "$0")/scripts/server.js" ~/clawd/tools/recall-local/server.js

# Create a LaunchAgent so it starts on login
cat > ~/Library/LaunchAgents/ai.wren.recall-local.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

Session Persistence

Medium
Category
Rogue Agent
Confidence
93% confidence
Finding

The PLIST content defines a persistent user-level service that will relaunch the Node server at login. Persistent execution of a service exposing searchable memory data can magnify privacy and local-network exposure risks if the service is misconfigured or forgotten.

Content

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

md
# Create a LaunchAgent so it starts on login
cat > ~/Library/LaunchAgents/ai.wren.recall-local.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key><string>ai.wren.recall-local</string>

Session Persistence

Medium
Category
Rogue Agent
Confidence
93% confidence
Finding

The PLIST content defines a persistent user-level service that will relaunch the Node server at login. Persistent execution of a service exposing searchable memory data can magnify privacy and local-network exposure risks if the service is misconfigured or forgotten.

Content

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

md
# Create a LaunchAgent so it starts on login
cat > ~/Library/LaunchAgents/ai.wren.recall-local.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key><string>ai.wren.recall-local</string>

Session Persistence

Medium
Category
Rogue Agent
Confidence
93% confidence
Finding

The LaunchAgent configuration specifies the program arguments for a background Node process, confirming an auto-starting service. Background services serving potentially sensitive local memory should not be installed implicitly because they persist outside the immediate user action.

Content

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

md
cat > ~/Library/LaunchAgents/ai.wren.recall-local.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key><string>ai.wren.recall-local</string>
  <key>ProgramArguments</key>

Session Persistence

Medium
Category
Rogue Agent
Confidence
86% confidence
Finding

The plist also configures persistent log files for the background service. While logging itself is not inherently malicious, logs can retain search activity, errors, or snippets of sensitive paths over time, adding another persistence and privacy dimension.

Content

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

md
<key>StandardOutPath</key><string>/Users/YOUR_USERNAME/clawd/tools/recall-local/recall.log</string>
  <key>StandardErrorPath</key><string>/Users/YOUR_USERNAME/clawd/tools/recall-local/recall.log</string>
</dict>
</plist>
EOF

# Replace YOUR_USERNAME, then load it

Session Persistence

Medium
Category
Rogue Agent
Confidence
92% confidence
Finding

Referencing the plist at load time confirms the persistence mechanism is intended to be installed and used. In the context of a searchable memory server, persistent auto-start broadens exposure duration and increases the likelihood the service remains active unnoticed.

Content

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

EOF

Replace YOUR_USERNAME, then load it

launchctl load ~/Library/LaunchAgents/ai.wren.recall-local.plist

text

Or just run it manually: `node ~/clawd/tools/recall-local/server.js &`

Session Persistence

Medium
Category
Rogue Agent
Confidence
92% confidence
Finding

Referencing the plist at load time confirms the persistence mechanism is intended to be installed and used. In the context of a searchable memory server, persistent auto-start broadens exposure duration and increases the likelihood the service remains active unnoticed.

Content

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

EOF

Replace YOUR_USERNAME, then load it

launchctl load ~/Library/LaunchAgents/ai.wren.recall-local.plist

text

Or just run it manually: `node ~/clawd/tools/recall-local/server.js &`

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The banner comment says the memory service is available at localhost, which implies loopback-only access, but the actual listener exposes it on all interfaces. This mismatch is dangerous because operators may trust the documentation and run the service in environments where other users or machines can access highly sensitive memory data.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The service is described and intended as a local memory search tool, but it binds to 0.0.0.0, making it reachable from other hosts on the network. Because it serves indexed contents of MEMORY.md, WORKING.md, and memory logs without authentication, any reachable client can query sensitive agent history, notes, or secrets stored in those files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

This endpoint exposes local memory contents over plain HTTP through an externally reachable interface and provides no authentication, authorization, or user-facing warning. In the context of an agent memory tool, the indexed files are especially sensitive because they may contain prior conversations, decisions, credentials, API keys, internal notes, or other confidential operational context.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The description frames the skill as indexing memory files, but the setup instructions also copy code into a tools directory, create a LaunchAgent, write logs, and install a persistent background service. That mismatch can mislead operators about the true system modifications being performed and reduce informed consent during execution.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.