Back to skill

Security audit

Smart Agent Memory

Security checks for vulnerabilities and agentic risk

Overview

This memory skill is broadly disclosed as a local long-term memory system, but it also persistently modifies agent startup files across workspaces and can write generated skills or Markdown files outside the intended memory scope.

Review this skill before installing. Only run setup if you intend every ~/.openclaw/workspace* directory to receive BOOTSTRAP.md instructions that steer future agent sessions. Avoid storing secrets or untrusted instructions in memory, and do not use extract or entity names from untrusted input until filename/path validation and generated-skill review controls are added.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (4)

T01 · Skill Instruction Hijacking

Error
Location
scripts/memory-cli.js:480
Finding

Persistent Cross-Workspace Agent Instruction Injection

Content
View full analysis
'; const BLOCK = ` ${MARKER} ## 🧠 Smart Agent Memory — Auto Start 每次 session 启动时,**在做任何事之前**,执行: \`\`\`bash node ~/.openclaw/skills/smart-agent-memory/scripts/memory-cli.js session-start \`\`\` 过程中有重要信息时立即保存: \`\`\`bash node ~/.openclaw/skills/smart-agent-memory/scripts/memory-cli.js remember "关键信息" --tags tag1,tag2 \`\`\` session 结束前保存摘要: \`\`\`bash node ~/.openclaw/skills/smart-agent-memory/scripts/memory-cli.js session-end "本次做了什么" \`\`\` > ⚠️ 不执行 session-start = 失忆。这是强制步骤,不是可选的。 ${MARKER} `; // Auto-discover ALL workspaces under ~/.openclaw/workspace* const openclawDir = path.join(os.homedir(), '.openclaw'); let workspaces = []; try { const entries = fs.readdirSync(openclawDir, { withFileTypes: true }); workspaces = entries .filter(e => e.isDirectory() && e.name.startsWith('workspace')) .map(e => path.join(openclawDir, e.name)); } catch (_) {} if (workspaces.length === 0) { // Fallback: just use default workspace workspaces = [path.join(openclawDir, 'workspace')]; } let injected = 0, skipped = 0; for (const wsDir of workspaces) { const bootstrapPath = path.join(wsDir, 'BOOTSTRAP.md'); let existing = ''; try { existing = fs.readFileSync(bootstrapPath, 'utf8'); } catch (_) {} if (existing.includes(MARKER)) { console.log(`${c.yellow('⚠')} Already injected: ${bootstrapPath}`); skipped++; } else { fs.writeFileSync(bootstrapPath, existing + BLOCK, 'utf8'); console.log(`${c.green('✓')} Injected: ${bootstrapPath}`); injec ...[truncated 2286 chars]
Remediation
View remediation

T02 · Agent Memory Poisoning

Error
Location
lib/store.js:88
Finding

Persistent Prompt Injection Through Untrusted Memory Content

Content
View full analysis
f.contentHash === contentHash && !f.supersededBy); if (dup) { return { id: dup.id, content, tags: [], deduplicated: true, _msg: `Duplicate of ${dup.id} (use --force to override)` }; } } const id = this._id(); const now = this._now(); if (skill) tags = [...new Set([...tags, `skill:${skill}`])]; const fact = { id, content, tags, source, confidence, skill: skill || null, owner, isPublic, contentHash, createdAt: now, lastAccessed: now, accessCount: 1, expiresAt: expiresInDays ? new Date(Date.now() + expiresInDays * 86400000).toISOString() : null, supersededBy: null, }; this.facts.push(fact); this._saveFacts(); // Also append to today's daily log (Markdown layer) this._appendDailyLog(`- **[${id}]** ${content}${tags.length ? ' `' + tags.join('`, `') + '`' : ''}`); // Per-skill experience memory file if (skill) { this._appendSkillMemory(skill, content, id); } return fact; } ``` The content is later printed into session context: ```javascript case 'session-start': { // Simulates mem9's before_prompt_build: load index + recent context console.log('📥 Session Start — Loading memory context...\n'); const idx = store.memor ...[truncated 3135 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
lib/store.js:329
Finding

Arbitrary Markdown File Write Through Entity-Name Path Traversal

Content
View full analysis
`- **${k}:** ${v}`).join('\n'); const md = [ `# ${entity.name}`, `**Type:** ${entity.entityType}`, `**First seen:** ${entity.firstSeen.slice(0, 10)}`, `**Last updated:** ${entity.lastUpdated.slice(0, 10)}`, '', attrs || '_(no attributes)_', ].join('\n'); try { const dirPath = path.join(this.memoryDir, dir); this._ensureDir(dirPath); fs.writeFileSync(path.join(dirPath, filename), md); } catch {} } ``` SQLite backend: ```javascript _writeEntityMd(entity) { const dir = entity.entityType === 'person' ? 'people' : 'decisions'; const dirPath = path.join(this.memoryDir, dir); this._ensureDir(dirPath); const filename = `${entity.name.toLowerCase().replace(/\s+/g, '-')}.md`; const attrs = Object.entries(entity.attributes).map(([k, v]) => `- **${k}:** ${v}`).join('\n'); const md = `# ${entity.name}\n**Type:** ${entity.entityType}\n**First seen:** ${entity.firstSeen.slice(0, 10)}\n**Last updated:** ${entity.lastUpdated.slice(0, 10)}\n\n${attrs || '_(no attributes)_'}\n`; try { fs.writeFileSync(path.join(dirPath, filename), md); } catch {} } ``` ### Technical Analysis The entity name is used to construct a filename after replacing whitespace only. Directory separators, `..` components, and other filesystem metacharacters remain intact. `path.join(dirPath, filename)` normalizes traversal components. A name containing components such as `../../target` can therefore resolve outside the intended `pe ...[truncated 1653 chars]
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
lib/extract.js:12
Finding

Unsafe Creation of Globally Loadable Skills from Untrusted Lesson Data

Content
View full analysis
[--skill-name my-skill]'); // Support both JSON store (.lessons array) and SQLite store (getLessons method) const allLessons = store.lessons || store.getLessons({ limit: 9999 }); const lesson = allLessons.find(l => l.id === lessonId); if (!lesson) return console.log(c.red(`Lesson ${lessonId} not found.`)); const skillDir = path.join(os.homedir(), '.openclaw', 'skills', skillName); const outFile = extractSkill(lesson, skillDir, skillName); console.log(`${c.green('✓')} Skill extracted: ${outFile}`); console.log(` From lesson: ${lesson.action}`); break; } ``` The generated Skill embeds lesson data verbatim: ```javascript function extractSkill(lesson, outputDir, skillName) { fs.mkdirSync(outputDir, { recursive: true }); const skillMd = `--- name: ${skillName} description: "Auto-extracted from lesson: ${lesson.action}" metadata: openclaw: trust: low --- # ${skillName} > Auto-generated from lesson **${lesson.id}** on ${lesson.createdAt.slice(0, 10)} ## Context ${lesson.context} ## What Happened ${lesson.action} ## Outcome **${lesson.outcome}** ## Insight / Best Practice ${lesson.insight} ## When to Use Apply this skill when you encounter a similar situation: - Context matches: ${lesson.context} - To avoid repeating: ${lesson.outcome === 'negative' ? 'the same mistake' : 'missing the opportunity'} --- *Extracted by smart-agent-memory skill extraction.* `; fs.writeFileSync(path.join(outputDir, 'SKI ...[truncated 2370 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (30)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

The skill is presented as a memory utility, but the documentation also describes setup behavior that scans multiple workspaces, injects BOOTSTRAP.md instructions, and writes generated artifacts into other locations such as ~/.openclaw/skills. Those side effects materially expand the trust boundary and can establish persistent behavioral control across workspaces without clear, up-front disclosure in the primary purpose statement.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The skill is presented as a memory utility, but the documentation also describes setup behavior that scans multiple workspaces, injects BOOTSTRAP.md instructions, and writes generated artifacts into other locations such as ~/.openclaw/skills. Those side effects materially expand the trust boundary and can establish persistent behavioral control across workspaces without clear, up-front disclosure in the primary purpose statement.

Content

No source excerpt is available for this finding.

Scope Creep

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The declared permissions only cover ~/.openclaw/workspace/memory, but the documented setup modifies BOOTSTRAP.md files across discovered ~/.openclaw/workspace* directories. That is a direct scope violation: if implemented, the skill would perform writes outside its declared authorization boundary, undermining permission-based trust and containment.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill states that all agents automatically search memory and that multiple agents may share one memory directory. That creates a broad disclosure surface where information persisted by one agent or conversation can be retrieved by unrelated agents or tasks, enabling cross-context leakage of private or sensitive data.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The CLI goes beyond a passive memory utility and includes a setup command that discovers all workspaces and injects mandatory bootstrap instructions into each BOOTSTRAP.md. This changes agent behavior across projects and creates persistence by steering future sessions to automatically load and store memory, which is risky for a component described as a memory system.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The setup command enumerates every discovered workspace and writes workflow instructions into each BOOTSTRAP.md without granular consent. This is effectively persistent cross-workspace configuration tampering: once run, future agents may follow injected instructions to execute memory commands and retain session data automatically.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The README instructs users to run a setup command that automatically discovers workspaces and injects a BOOTSTRAP.md file, but it does not clearly foreground that this will modify files in user workspaces before the command is run. In an agent-skill context, automatic cross-workspace writes are security-relevant because users or agents may execute setup based on documentation alone, causing unintended persistence or instruction injection into multiple directories.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding

Without declared permissions the skill's intent is opaque and cannot be validated.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The natural-language content of the skill is entirely in Chinese and uses imperative guidance for agent behavior, but it does not offer users a language option or explain that the skill is intended only for a Chinese-speaking or region-specific environment. Under the language/locale policy, forcing a specific language without opt-in is a policy concern.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The manifest suggests the skill is limited to ~/.openclaw/workspace/memory, but the setup instructions describe scanning all ~/.openclaw/workspace* directories and injecting BOOTSTRAP.md into each. This mismatch can cause users and platform policy engines to under-estimate the skill's reach, enabling broader modification than expected.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

Injecting BOOTSTRAP.md instructions into discovered workspaces gives the skill a persistence and influence mechanism beyond ordinary memory storage. Because BOOTSTRAP content can shape future agent behavior, this capability is security-relevant and should not be bundled implicitly into a storage utility.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Automatically injecting BOOTSTRAP.md across discovered workspaces is a sensitive action because it changes files in multiple locations and can affect future agent behavior. The documentation does not foreground this as a high-risk modification with explicit warnings and consent, increasing the chance of silent or poorly understood propagation.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

Automatically scanning all workspaces and injecting memory-related bootstrap instructions expands both collection scope and future exposure of data across otherwise separate contexts. This creates a persistence and propagation path that can normalize storing and recalling data from multiple workspaces without clear segmentation.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The instructions encourage broad, continuous persistence of conversation-derived information, including session summaries and ad hoc facts, without visible safeguards for secrets, personal data, or minimization. In a shared or long-lived agent environment, this can cause inadvertent retention of sensitive user content that later becomes searchable and reusable beyond the original context.

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 · lib/extract.js (reported line 12)May include surrounding context.

js
/**
 * Extract a lesson into a skill template.
 * @param {object} lesson - Lesson object from store
 * @param {string} outputDir - Where to write the skill (e.g., ~/.openclaw/skills/<name>)
 * @param {string} skillName - Skill name (slug)
 */
function extractSkill(lesson, outputDir, skillName) {

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
84% confidence
Finding

The manifest describes a long-term agent memory system focused on layered context, structured storage, search, and archiving. This function goes beyond memory storage/retrieval by generating a new SKILL.md artifact intended for agent skill reuse, which is a distinct capability not clearly covered by the stated purpose.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The top-level comment explicitly promises 'No external dependencies'. Later, the module imports execFileSync and uses it to run qmd, which is an external system dependency. This is a direct contradiction between documentation and implementation, not merely omitted detail.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The manifest emphasizes '纯 Node.js 原生模块,零外部依赖', and this file's header also says 'No external dependencies'. Yet smartSearch depends on spawning the external qmd binary when available. Invoking a host-installed executable is a capability beyond a self-contained native-module implementation and is not clearly justified by the stated no-dependency scope.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

smartSearch accepts a dir parameter but does not constrain the qmd invocation to that directory, so the effective search scope depends on the external tool's current working directory or its own defaults. In a memory system, this can cause unintended cross-project or cross-tenant data exposure by returning results from outside the requested memory root.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

This code stores skill data to disk in multiple places, including writing the index file and later persisting facts, lessons, entities, and daily logs. While the file has a high-level header describing the storage backend, it does not provide a user-facing warning, confirmation, or explicit disclosure that user-provided content will be written persistently to local markdown and database files.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The forget and forgetStale methods delete stored facts from the database, and one path performs bulk deletion of stale records. There is no visible confirmation prompt, user-facing log, or nearby warning comment indicating that data may be permanently removed.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
85% confidence
Finding

The manifest describes a long-term memory system with SQLite/FTS5-backed high-performance full-text search, but this file's actual MemoryStore search implementation is a simple includes-based scan over loaded facts. Although createStore can select a SQLite backend if available, the concrete behavior implemented in this file does not match the stronger storage/search claims in the manifest and top-of-file documentation.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
86% confidence
Finding

The extract command writes new skill content under ~/.openclaw/skills/<skillName> based on stored lesson data. Even though this appears intended as feature automation, it creates executable or trusted agent content from prior memory data, which can become a persistence or prompt-injection vector if lessons contain unsafe content or if skillName is not tightly constrained.

Content

No source excerpt is available for this finding.

Ssd 4

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The injected startup narrative establishes a mandatory workflow of loading context at session start, recording details during execution, and saving summaries at the end. This creates behavioral persistence that can amplify data exposure and prompt-injection effects over time, especially because the skill is specifically designed for long-term cross-session memory.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The injected BOOTSTRAP.md block contains operational instructions entirely in Chinese and states the process is mandatory. This imposes a language/locale choice on all target workspaces without offering user selection or documenting a justified regional constraint.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.