Back to skill

Security audit

Openclaw Memory

Security checks for vulnerabilities and agentic risk

Overview

This memory skill does what it advertises, but it needs review because it automatically stores conversation data, exposes weakly scoped memory/payment APIs, and makes privacy claims that conflict with its default remote embedding behavior.

Review before installing. Use local embeddings unless you explicitly accept sending memory text and search queries to OpenAI, do not store secrets or regulated data, do not expose the dashboard without authentication, and do not give agents funded wallet access without explicit spending caps and human approval.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
src/dashboard.js:43
Finding

Unauthenticated Persistent Memory Poisoning Enables Cross-Session Prompt Injection

Content
View full analysis
{ try { const { agent_wallet, content, type, importance, session_id } = req.body; if (!agent_wallet) { return res.status(400).json({ error: 'agent_wallet is required' }); } if (!content || typeof content !== 'string') { return res.status(400).json({ error: 'content is required and must be a string' }); } const manager = getMemoryManager(); const memory = await manager.storeMemory( agent_wallet, content, type || 'fact', importance || 0.5, session_id ); ``` ```js // hooks/request-before.js:32-54 const memories = await manager.retriever.retrieveRelevant(query, { agent_wallet: agentWallet, limit: 5, // Top 5 most relevant memories min_score: 0.7 // Minimum similarity threshold }); // Inject memories into request context if (memories && memories.length > 0) { // Format memories for injection const memoryContext = memories.map(m => ({ type: m.memory_type, content: m.content, importance: m.importance_score, timestamp: m.timestamp })); // Add to request data requestData.context = requestData.context || {}; requestData.context.memories = memoryContext; // Also format as text for prompt injection const memoryText = memories .map(m => `[${m.memory_type}] ${m.content}`) .join('\n'); requestData.context.memory_text = memoryText; ``` ```js // src/dashboard.js:405-410 app.listen(port, () => { console.log(`\n${'='.repeat(70)}`); console.log(` OpenClaw Memory System - REST API Dashboard`); console.log(`${'='.repeat(70)}`); console.log(` Status: Running`); console.log(` URL: http://localhost:${port}`); ``` ...[truncated 2642 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/dashboard.js:100
Finding

Unauthenticated Memory Search, Enumeration, and Deletion

Content
View full analysis
{ try { const { agent_wallet, query, limit, min_score } = req.query; if (!agent_wallet) { return res.status(400).json({ error: 'agent_wallet is required' }); } if (!query) { return res.status(400).json({ error: 'query is required' }); } const manager = getMemoryManager(); const memories = await manager.retrieveMemories(agent_wallet, query, { limit: limit ? parseInt(limit) : 5, min_score: min_score ? parseFloat(min_score) : 0.7 }); res.json({ query, count: memories.length, memories: memories.map(m => ({ memory_id: m.memory_id, content: m.content, type: m.memory_type, importance: m.importance_score, similarity_score: m.similarity_score, timestamp: m.timestamp, accessed_count: m.accessed_count })) }); ``` ```js // src/dashboard.js:154-181 app.get('/api/memories/recent', async (req, res) => { try { const { agent_wallet, limit, type } = req.query; if (!agent_wallet) { return res.status(400).json({ error: 'agent_wallet is required' }); } const manager = getMemoryManager(); let memories; if (type) { memories = await manager.retriever.getByType(agent_wallet, type); memories = memories.slice(0, limit ? parseInt(limit) : 10); } else { memories = await manager.retriever.getRecent( agent_wallet, limit ? parseInt(limit) : 10 ); } res.json({ count: memories.length, memories: memories.map(m => ({ memory_id: m.memory_id, content: m.content, type: m.memory_type, im ...[truncated 2558 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/embeddings.js:17
Finding

Conversation-Derived Content Is Sent to OpenAI by Default Despite Local-Only Privacy Claims

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/x402.js:67
Finding

Fabricated Transaction Hashes Grant Pro Licenses Without Payment

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
hooks/request-after.js:41
Finding

Quota Enforcement Is Bypassed Because a Result Object Is Treated as a Boolean

Content
View full analysis
0, remaining: Math.max(0, remaining), limit: quota.memory_limit, tier: quota.tier }; } ``` ```js // hooks/request-after.js:41-50 const quota = await manager.storage.getQuota(agentWallet); const quotaAvailable = await manager.storage.checkQuotaAvailable(agentWallet); if (quotaAvailable) { // Store memories directly for (const memory of memories) { await manager.storage.recordMemory({ ...memory, agent_wallet: agentWallet, session_id: request.sessionId || requestId }); } ``` ```js // src/index.js:81-84 const quotaAvailable = await this.storage.checkQuotaAvailable(agentWallet); if (!quotaAvailable) { await this.pruner.enforceQuota(agentWallet); } ``` ### Technical Analysis `checkQuotaAvailable()` returns an object in every normal execution path. JavaScript objects are truthy regardless of the value of their `available` property. In the request-after hook, `if (quotaAvailable)` therefore always enters the direct-storage branch. In `MemoryManager.afterRequest()`, `if (!quotaAvailable)` is always false. The intended quota-exhaustion and pruning branches are consequently unreachable based on a normal returned quota object. Because the memory API is also unauthenticated, this defect can be combined with repeated submissions to produce persistent database ...[truncated 1096 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (66)

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · IMPLEMENTATION-SUMMARY.md (reported line 45)May include surrounding context.

md
- `POST /api/memories` - Store new memory
     - `GET /api/memories/search` - Semantic search
     - `GET /api/memories/recent` - List recent memories
     - `DELETE /api/memories/:id` - Delete memory
     - `GET /api/memories/stats` - Get statistics
   - x402 payment endpoints:
     - `POST /api/x402/subscribe` - Create payment request

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · README.md (reported line 193)May include surrounding context.

md
- `POST /api/memories` - Store new memory
     - `GET /api/memories/search` - Semantic search
     - `GET /api/memories/recent` - List recent memories
     - `DELETE /api/memories/:id` - Delete memory
     - `GET /api/memories/stats` - Get statistics
   - x402 payment endpoints:
     - `POST /api/x402/subscribe` - Create payment request

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · src/cli.js (reported line 156)May include surrounding context.

js
- `POST /api/memories` - Store new memory
     - `GET /api/memories/search` - Semantic search
     - `GET /api/memories/recent` - List recent memories
     - `DELETE /api/memories/:id` - Delete memory
     - `GET /api/memories/stats` - Get statistics
   - x402 payment endpoints:
     - `POST /api/x402/subscribe` - Create payment request

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · src/dashboard.js (reported line 421)May include surrounding context.

js
- `POST /api/memories` - Store new memory
     - `GET /api/memories/search` - Semantic search
     - `GET /api/memories/recent` - List recent memories
     - `DELETE /api/memories/:id` - Delete memory
     - `GET /api/memories/stats` - Get statistics
   - x402 payment endpoints:
     - `POST /api/x402/subscribe` - Create payment request

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · src/pruner.js (reported line 99)May include surrounding context.

js
- `POST /api/memories` - Store new memory
     - `GET /api/memories/search` - Semantic search
     - `GET /api/memories/recent` - List recent memories
     - `DELETE /api/memories/:id` - Delete memory
     - `GET /api/memories/stats` - Get statistics
   - x402 payment endpoints:
     - `POST /api/x402/subscribe` - Create payment request

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · src/pruner.js (reported line 206)May include surrounding context.

js
- `POST /api/memories` - Store new memory
     - `GET /api/memories/search` - Semantic search
     - `GET /api/memories/recent` - List recent memories
     - `DELETE /api/memories/:id` - Delete memory
     - `GET /api/memories/stats` - Get statistics
   - x402 payment endpoints:
     - `POST /api/x402/subscribe` - Create payment request

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · IMPLEMENTATION-SUMMARY.md (reported line 45)May include surrounding context.

md
- `POST /api/memories` - Store new memory
     - `GET /api/memories/search` - Semantic search
     - `GET /api/memories/recent` - List recent memories
     - `DELETE /api/memories/:id` - Delete memory
     - `GET /api/memories/stats` - Get statistics
   - x402 payment endpoints:
     - `POST /api/x402/subscribe` - Create payment request

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README encourages autonomous payment for a paid tier and explicitly says no human approval is needed, without strong billing or authorization warnings. That can normalize real-money spending by agents and lead to unauthorized subscriptions, financial loss, or abuse when deployed in permissive agent environments.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The documented behavior automatically extracts and persistently stores facts, preferences, patterns, and conversations, including examples of sensitive content. In a memory skill, this creates a substantial privacy and secret-retention risk because users may unknowingly have credentials, personal data, or sensitive business context stored across sessions.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · README.md (reported line 194)May include surrounding context.

md
GET /api/memories/recent?agent_wallet=0x...&limit=10

# Delete memory
DELETE /api/memories/:memory_id?agent_wallet=0x...

# Get stats
GET /api/memories/stats?agent_wallet=0x...

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The README makes a strong privacy claim that all data stays local and nothing is sent to external servers, yet elsewhere documents OpenAI as the default embedding provider. That mismatch can mislead users into exposing conversation-derived memories to a third party under false assumptions, which is a real security/privacy issue even in documentation.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

This hook automatically analyzes the full user prompt and agent response and stores derived 'memories' tied to an agent wallet and session, with no consent, notice, opt-in, or filtering visible in this code. That creates a significant privacy and data-governance risk because sensitive user content may be retained after every interaction, potentially beyond user expectations and without minimization.

Content

No source excerpt is available for this finding.

Context Leakage

High
Category
Data Exfiltration
Confidence
85% confidence
Finding

Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.

Content

Scanner excerpt · hooks/session-end.js (reported line 33)May include surrounding context.

js
// Check license status
    const license = manager.x402.hasValidLicense(agentWallet);

    // Log session summary
    console.log(`\n========================================`);
    console.log(`[Memory System] Session ${sessionId} ended`);
    console.log(`========================================`);

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
97% confidence
Finding

The DELETE /api/memories/:id endpoint performs a destructive action based only on user-supplied agent_wallet and memory ID, with no visible authentication, authorization, or ownership verification in this file. An attacker who can guess or obtain another wallet identifier and memory ID may be able to delete stored memories, causing integrity loss and potential denial of service against other users' data.

Content

Scanner excerpt · src/dashboard.js (reported line 194)May include surrounding context.

js
});

/**
 * DELETE /api/memories/:id
 * Delete a specific memory
 *
 * Query params:

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · src/dashboard.js (reported line 421)May include surrounding context.

js
console.log(`    POST   /api/memories              Store new memory`);
  console.log(`    GET    /api/memories/search       Semantic search`);
  console.log(`    GET    /api/memories/recent       List recent memories`);
  console.log(`    DELETE /api/memories/:id          Delete memory`);
  console.log(`    GET    /api/memories/stats        Get statistics`);
  console.log(`    POST   /api/x402/subscribe        Create payment request`);
  console.log(`    POST   /api/x402/verify           Verify payment`);

Memory Manipulation

High
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Content

Scanner excerpt · src/index.js (reported line 169)May include surrounding context.

js
const quota = await this.storage.getQuota(agentWallet);
      await this.storage.updateQuota(agentWallet, { memory_count: Math.max(0, quota.memory_count - 1) });
    } catch (error) {
      throw new Error(`Failed to delete memory: ${error.message}`);
    }
  }

Intent-Code Divergence

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

This is a real vulnerability: the code claims to verify payments on-chain, but verifyTransactionOnChain returns true for any sufficiently long txHash. An attacker can submit a fake hash and obtain a paid Pro license with unlimited memory without sending funds, causing direct revenue loss and unauthorized access to premium functionality.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document explicitly encourages autonomous agents to initiate cryptocurrency payments before presenting strong, upfront operator-authorization and irreversibility warnings. In the context of an agent skill, this can normalize unattended spending behavior and increase the chance that an integrated agent will make irreversible transfers without meaningful human approval or spending limits.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · AGENT-PAYMENTS.md (reported line 157)May include surrounding context.

md
async function subscribeToPro() {
  // Step 1: Create payment request
  const response = await fetch('http://localhost:9091/api/x402/subscribe', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ agent_wallet: myWallet })

Internal Network Request

Medium
Category
Server-Side Request Forgery
Confidence
70% confidence
Finding

Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Content

Scanner excerpt · AGENT-PAYMENTS.md (reported line 157)May include surrounding context.

md
async function subscribeToPro() {
  // Step 1: Create payment request
  const response = await fetch('http://localhost:9091/api/x402/subscribe', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ agent_wallet: myWallet })

Internal Network Request

Medium
Category
Server-Side Request Forgery
Confidence
70% confidence
Finding

Code issues a request to a loopback, link-local, or private-range host. This can reach internal services not meant to be exposed and is a common SSRF pivot.

Content

Scanner excerpt · AGENT-PAYMENTS.md (reported line 174)May include surrounding context.

md
async function subscribeToPro() {
  // Step 1: Create payment request
  const response = await fetch('http://localhost:9091/api/x402/subscribe', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ agent_wallet: myWallet })

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · AGENT-PAYMENTS.md (reported line 174)May include surrounding context.

md
});

  // Step 3: Verify payment
  const verifyResponse = await fetch('http://localhost:9091/api/x402/verify', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Telling operators to give agents access to a funded wallet without adjacent guidance on least privilege, capped balances, recipient restrictions, and irreversible-loss risk is unsafe. This materially increases the chance of overbroad wallet delegation, where an agent or compromised workflow can spend funds beyond the operator's intended scope.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · IMPLEMENTATION-SUMMARY.md (reported line 124)May include surrounding context.

API examples:

bash
# Store memory
curl -X POST http://localhost:9091/api/memories \
  -H "Content-Type: application/json" \
  -d '{
    "agent_wallet": "0x123...",

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill explicitly states that hooks automatically inject memories before requests and extract/store memories after responses, but the summary provides no indication of user consent, notice, opt-in controls, or privacy boundaries. In a memory system handling conversation content and preferences, silent collection and reinjection can expose sensitive user data across interactions and increase the chance of unintended retention or disclosure.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
src/embeddings.js:18