Back to skill

Security audit

多用户隔离型长期记忆 Multi-user Long Term Memory

Security checks for vulnerabilities and agentic risk

Overview

This skill is purpose-built for multi-user long-term memory, but its local persistence design can mix users and preserve untrusted content without clear controls.

Review before installing in any shared or production environment. This skill only uses local files and has no external dependency or network behavior, but it stores user identifiers and memory indefinitely, and its sender-ID-to-filename mapping can collide. Use it only where caller identities are trusted, users have consented to persistent memory, and there is a clear process to review, delete, and treat stored memories as untrusted user data.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
references/user-memory.js:30
Finding

User identifier collisions allow cross-user memory access and modification

Content
View full analysis

Vulnerability Details

File Location: references/user-memory.js, lines 30–67
Vulnerability Type: Insufficiently unique user identifier canonicalization
Risk Level: High

Vulnerable Code

javascript
function extractUsername(senderId) {
  if (!senderId) {
    return 'unknown';
  }
  // Take the portion before |, or the entire value if | is absent
  const username = senderId.split('|')[0];
  // Sanitize the filename by replacing unsafe characters
  return username.replace(/[^a-zA-Z0-9_-]/g, '_');
}

function getUserMemoryPath(senderId) {
  const username = extractUsername(senderId);
  return path.join(USERS_DIR, `${username}.md`);
}

function get(userId) {
  ensureDir();
  const memoryPath = getUserMemoryPath(userId);

  if (fs.existsSync(memoryPath)) {
    return fs.readFileSync(memoryPath, 'utf-8');
  }
  return '';
}

function save(userId, content) {
  ensureDir();
  const memoryPath = getUserMemoryPath(userId);
  fs.writeFileSync(memoryPath, content, 'utf-8');
}

Technical Analysis

The memory filename is derived by taking only the portion of senderId before the first | and replacing every character outside [a-zA-Z0-9_-] with an underscore. This transformation is not collision-resistant.

Distinct user identifiers can consequently resolve to the same file. For example:

  • alice/admin|session-1
  • alice.admin|session-2
  • alice_admin|session-3

All three identifiers resolve to users/alice_admin.md. The implementation does not maintain a verified mapping between the original identifier and the resulting file, nor does it validate that the caller is authorized to access the selected memory.

The same derived path is used by get, save, and append. A collision therefore affects the confidentiality and integrity of another user's persistent memory.

Attack Path

  1. An attacker identifies or guesses the filename-compatible identity o ...[truncated 1177 chars]
Remediation
View remediation

Remediation Suggestions

  1. Derive storage keys from a collision-resistant encoding of the complete canonical user identifier, such as a SHA-256 digest.
  2. Do not discard the portion after | unless a trusted authentication layer has already established that it is only a session identifier.
  3. Maintain a protected mapping between the complete authenticated identity and its memory file.
  4. Verify authorization before every read or write instead of relying on caller-supplied identifiers as proof of identity.
  5. Store the canonical identity inside the file or metadata and reject access when it does not match the authenticated identity.
  6. Add tests covering identifiers that differ only by punctuation, empty identifiers, repeated delimiters, Unicode characters, and values that normalize to unknown.
  7. Migrate existing files carefully so that previously colliding users are assigned separate storage records.

T02 · Agent Memory Poisoning

Error
Location
references/user-memory.js:59
Finding

Untrusted content can poison persistent Agent memory

Content
View full analysis

Vulnerability Details

File Location: references/user-memory.js, lines 59–86
Vulnerability Type: Unvalidated attacker-controlled persistent memory content
Risk Level: High

Vulnerable Code

javascript
function save(userId, content) {
  ensureDir();
  const memoryPath = getUserMemoryPath(userId);
  fs.writeFileSync(memoryPath, content, 'utf-8');
}

function append(userId, content) {
  ensureDir();
  const memoryPath = getUserMemoryPath(userId);

  let existingContent = '';
  if (fs.existsSync(memoryPath)) {
    existingContent = fs.readFileSync(memoryPath, 'utf-8');
  }

  const timestamp = new Date().toISOString();
  const newEntry = `\n\n## ${timestamp}\n${content}`;

  fs.writeFileSync(memoryPath, existingContent + newEntry, 'utf-8');
}

Technical Analysis

The exported save() and append() functions persist arbitrary caller-controlled strings directly into long-term memory. The data has no provenance metadata, trust classification, schema validation, field restrictions, or separation between ordinary user facts and instruction-like text.

The Skill is explicitly designed to retrieve these files as Agent memory in later sessions. If the consuming Agent inserts the returned Markdown into its context without treating it strictly as untrusted data, an attacker can store prompt-like rules that continue influencing subsequent conversations.

The issue can be exploited directly by any untrusted caller allowed to invoke the write functions. It can also be combined with the identifier-collision vulnerability to poison another user's memory.

Attack Path

  1. An attacker obtains access to save() or append(), or selects an identifier that collides with a victim's memory file.
  2. The attacker submits content framed as persistent instructions, false facts, or directives to ignore later constraints.
  3. The function writes the content verbatim to a Markdown memory file.

...[truncated 1127 chars]

Remediation
View remediation

Remediation Suggestions

  1. Require authenticated and authorized identities for all memory writes.
  2. Replace raw Markdown persistence with a structured schema containing defined fields, provenance, timestamps, writer identity, and trust level.
  3. Validate field types, lengths, and permitted content before storage.
  4. Keep user-provided data logically separated from Agent instructions and system policy.
  5. When memory is retrieved, explicitly mark it as untrusted historical user data and prevent the consuming Agent from interpreting it as executable instructions.
  6. Permit only trusted application logic—not arbitrary callers—to promote content into durable memory.
  7. Add review, deletion, versioning, and rollback controls for persistent records.
  8. Apply size and entry-count limits to reduce persistent flooding and storage exhaustion.
  9. Record audit events for memory creation, replacement, and modification.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (6)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The skill description is written as an instruction for OpenClaw Agent in Chinese, and the usage examples store a preference to communicate in Simplified Chinese. There is no indication that language is user-selectable or that the skill is limited to a Chinese-only context, which conflicts with the policy against forcing a specific language without opt-in.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill explicitly describes persistent, per-user storage of memory across sessions but does not mention any user notice, consent, retention limit, or guidance on handling sensitive data. This creates a privacy and data-governance risk because personal preferences, context, or other identifying information may be stored indefinitely without transparency or controls.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This module persistently stores per-user data to local markdown files and exposes CLI commands that can create, overwrite, and append memory without any consent prompt, retention notice, or access-control checks. In a multi-user agent context, silent long-term storage of user identifiers and content increases privacy and compliance risk, especially because the header records both username and sender ID.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The file states "偏好:使用简体中文交流" as an instruction/preference to communicate in Simplified Chinese. Under the policy rules, language constraints should not be forced unless the user is explicitly offered a language choice or the locale restriction is clearly justified.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

The natural-language instructions and descriptions are entirely in Chinese, which can impose a language constraint on users or operators without any opt-in or explanation. The file does not indicate that the skill is intended only for a Chinese-speaking or region-specific context.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
83% confidence
Finding

Natural-language strings in comments and CLI help are partly in Chinese, which may impose a language expectation on users or maintainers without explicit opt-in or locale justification. The file does not indicate that the skill is region-specific or provide a multilingual choice.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.