Back to skill

Security audit

Micro Memory

Security checks for vulnerabilities and agentic risk

Overview

This is a local memory tool, but it needs review because it stores personal memory data persistently, has broad automatic triggers, ships a broken package manifest, and includes an unsafe alternate command launcher.

Review carefully before installing. Do not store secrets or highly sensitive personal data unless you are comfortable with plaintext local files, markdown backups, archives, and exports. Avoid using bin/memory.js; use only the declared dist/index.js entry point after the package manifest is fixed. Treat CSV exports as untrusted if memory content can come from other people, and prefer explicit memory commands over broad auto-trigger use.

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

T09 · Insecure Skill Coding Practices

Error
Location
bin/memory.js:9
Finding
Shell Command Injection in Alternate CLI Launcher<![CDATA[ ## Vulnerability Details **File Location**: `bin/memory.js:9-20` **Vulnerability Type**: OS command injection through unsafe shell command construction **Risk Level**: High ### Vulnerable Code ```javascript // Forward all arguments to the compiled script const args = process.argv.slice(2).map(arg => { // Properly escape arguments for Windows if (arg.includes(' ') || arg.includes('"')) { return `"${arg.replace(/"/g, '\\"')}"`; } return arg; }).join(' '); try { execSync(`node "${distPath}" ${args}`, { stdio: 'inherit', windowsHide: true }); ``` ### Technical Analysis The launcher concatenates user-controlled command-line arguments into a single string and passes that string to `execSync`. When `execSync` receives a string, Node.js executes it through the platform shell. The custom escaping only handles spaces and double quotes. It does not safely encode shell metacharacters such as: - `;`, `|`, `&`, `$()`, and backticks on POSIX shells - `&`, `|`, `^`, `%`, and redirection operators on Windows command interpreters Arguments without spaces or double quotes are inserted without any escaping. Quoting arguments with spaces also does not provide portable shell escaping. Consequently, an attacker who can influence an argument passed to this launcher may terminate or extend the intended command and execute an additional operating-system command. Although the current npm `bin` mapping points to `dist/index.js`, this alternate launcher remains directly executable and is explicitly implemented as a CLI entry point. ### Attack Path 1. A user, automation system, or Agent invokes `node bin/memory.js` with an attacker-influenced argument. 2. The launcher joins that argument into the `args` string. 3. The string is interpolated into ``node "${distPath}" ${args}``. 4. `execSync` submits the resulting string to the system shell. 5. The shell interprets embedded metacharacters and executes the injected command. A POSIX attack can have ...[truncated 754 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Do not pass user-controlled arguments through a shell. Replace command-string construction with an argument-array API such as `execFileSync` or `spawnSync`: ```javascript const path = require('path'); const { execFileSync } = require('child_process'); const distPath = path.join(__dirname, '..', 'dist', 'index.js'); try { execFileSync(process.execPath, [distPath, ...process.argv.slice(2)], { stdio: 'inherit', windowsHide: true }); } catch (error) { process.exit( typeof error.status === 'number' ? error.status : 1 ); } ``` Additional hardening measures: 1. Remove `bin/memory.js` if it is unused. 2. Avoid setting `shell: true` in any replacement implementation. 3. Use `process.execPath` rather than relying on a shell-resolved `node` command. 4. Add regression tests containing shell metacharacters and verify that they are forwarded as literal arguments. 5. Ensure all documented and packaged entry points use the same shell-free implementation. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/archive.ts:99
Finding
Spreadsheet Formula Injection in CSV Export<![CDATA[ ## Vulnerability Details **File Location**: `src/archive.ts:99-117` **Vulnerability Type**: CSV/spreadsheet formula injection **Risk Level**: Medium The corresponding compiled implementation is also present in `dist/archive.js:121-139`. ### Vulnerable Code ```typescript } else if (format === 'csv') { const exportFile = path.join(process.cwd(), `memory_export_${timestamp}.csv`); const lines = ['id,content,tag,type,importance,timestamp,strength_score,strength_level']; for (const memory of memories) { const row = [ memory.id, `"${memory.content.replace(/"/g, '""')}"`, memory.tag || '', memory.type || '', memory.importance || '', memory.timestamp, memory.strength.score, memory.strength.level, ].join(','); lines.push(row); } fs.writeFileSync(exportFile, lines.join('\n'), 'utf-8'); printColored(`✓ Exported to ${exportFile}`, 'green'); ``` ### Technical Analysis Memory content and tags can contain user-controlled text. The exporter doubles quotes in the content field, which addresses part of CSV structural escaping, but it does not neutralize spreadsheet formulas. Spreadsheet applications may interpret a cell as a formula when its value begins with characters such as: - `=` - `+` - `-` - `@` - Tab or carriage-return control characters in some applications Enclosing a value in CSV double quotes does not necessarily prevent formula evaluation. Other string fields, including `tag` and `type`, are not consistently CSV-quoted and can also contain delimiters or formula-leading values. For example, a stored memory whose content begins with a spreadsheet formula remains formula-capable in the exported CSV when opened in a compatible spreadsheet application. ### Attack Path 1. An attacker causes malicious formula-like text to be stored in a memory or tag. 2. The victim runs: ```bash memory export --format=csv ``` 3. The Skill writes the attacker-controlled text into the CSV wit ...[truncated 935 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Apply a single defensive CSV-encoding function to every exported field. The function should: 1. Convert the value to text. 2. Detect formula-leading characters after any leading whitespace. 3. Prefix dangerous values with an apostrophe or another application-appropriate neutralization character. 4. Escape embedded double quotes. 5. Quote every string field consistently. Example: ```typescript function encodeCsvCell(value: unknown): string { let text = String(value ?? ''); if (/^[\s]*[=+\-@]/.test(text) || /^[\t\r]/.test(text)) { text = `'${text}`; } return `"${text.replace(/"/g, '""')}"`; } ``` Use it for every field: ```typescript const row = [ memory.id, memory.content, memory.tag, memory.type, memory.importance, memory.timestamp, memory.strength.score, memory.strength.level, ].map(encodeCsvCell).join(','); ``` Also: - Add tests for values beginning with `=`, `+`, `-`, `@`, tabs, carriage returns, commas, quotes, and newlines. - Document that exported records may originate from untrusted users. - Regenerate `dist/archive.js` after correcting the TypeScript source. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/utils.ts:156
Finding
Denial of Service Through Unbounded User-Controlled Regular Expressions<![CDATA[ ## Vulnerability Details **File Location**: `src/utils.ts:156-164` **Vulnerability Type**: Regular-expression denial of service and unsafe dynamic regular-expression construction **Risk Level**: Medium Related unsafe construction also occurs at `src/utils.ts:194`, and the functionality is reachable through regex search handling in `src/memory.ts:120-132`. ### Vulnerable Code ```typescript /** * 正则表达式匹配 */ export function regexMatch(text: string, pattern: string): boolean { try { const regex = new RegExp(pattern, 'i'); return regex.test(text); } catch (e) { // 如果正则无效,回退到普通包含匹配 return text.toLowerCase().includes(pattern.toLowerCase()); } } ``` A second dynamic expression is constructed during relevance scoring: ```typescript else if (new RegExp(`\\b${normalizedKw}\\b`, 'i').test(content)) { score += 5; } ``` The regex search is reached using user-controlled CLI input: ```typescript if (useRegex) { // 正则模式 return regexMatch(text, keyword); } else if (useFuzzy) { ``` ### Technical Analysis The `--regex` search mode compiles an arbitrary user-supplied pattern using JavaScript's backtracking regular-expression engine and executes it synchronously against stored memory content. Certain nested or ambiguous patterns can cause catastrophic backtracking. Processing time may grow exponentially with input length, blocking the Node.js event loop. The `try/catch` only handles syntax errors; it cannot interrupt a valid expression that consumes excessive CPU. The relevance-scoring expression separately inserts `normalizedKw` into a regular-expression pattern without escaping regex metacharacters. A malformed keyword can therefore throw an exception and terminate the command. A crafted valid pattern may also create unnecessary backtracking. ### Attack Path 1. An attacker controls or influences a search query submitted to the Skill. 2. The query is supplied with the `--regex` option and contains a pathological backtracking patt ...[truncated 1066 chars]
Remediation
<![CDATA[ ## Remediation Suggestions The safest approach is to remove arbitrary regex support and use literal or tokenized search. If regex support is required: 1. Set strict maximum lengths for patterns and searched text. 2. Reject known-dangerous nested quantifiers and ambiguous repetition. 3. Use a regular-expression safety analyzer before execution. 4. Prefer a non-backtracking engine such as RE2-compatible bindings. 5. Run regex evaluation in an isolated worker process or worker thread that can be terminated after a short timeout. 6. Limit the number and size of memory records processed by one query. 7. Catch compilation errors at every dynamic `RegExp` construction. For relevance scoring, escape keywords before interpolation: ```typescript function escapeRegExp(value: string): string { return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } const escapedKeyword = escapeRegExp(normalizedKw); if (new RegExp(`\\b${escapedKeyword}\\b`, 'i').test(content)) { score += 5; } ``` For explicit regex mode, enforce bounded input before compilation: ```typescript if (pattern.length > 200 || text.length > 10_000) { return false; } ``` Length restrictions alone are not a complete defense against catastrophic backtracking, so they should be combined with a safe engine or execution timeout. Rebuild the compiled `dist` files after remediation. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (27)

Missing User Warnings

Medium
Confidence
89% confidence
Finding
This markdown file lists commands such as `memory delete`, `memory compress`, `memory archive`, and `memory export`, which can delete, alter, move, or disclose stored user memory data. The description does not provide any warning about data loss, privacy implications, backups, or confirmation behavior, so users are not alerted to safety-relevant effects.

Missing User Warnings

Medium
Confidence
81% confidence
Finding
The documentation states that memory contents are stored in local files such as `store/store.md` and `index.json`, and elsewhere mentions export to JSON/CSV. Because this skill stores potentially sensitive user memory content on disk and supports export, the markdown should warn users about local data exposure and handling of exported files.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The skill explicitly describes persistent storage, backups, and archiving of user memories, but does not warn users about retention, restoration, or the sensitivity of stored content. For a 'second brain' tool, this increases privacy risk because users may disclose intimate or confidential information without understanding that it will be retained across multiple local files and archives.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The documented auto-trigger phrases are broad, natural-language commands that can appear in ordinary conversation, which makes unintended invocation plausible. In a memory skill, accidental triggering can silently store, search, or reveal personal information, especially because the feature is framed as automatic and always-on within the host assistant.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
This code builds a single shell command string and passes user-controlled arguments into execSync, relying on ad hoc quoting that only handles spaces and double quotes. Shell metacharacters such as &, |, ;, $, backticks, parentheses, and platform-specific quoting/escaping behaviors can still alter command execution, leading to command injection when an attacker controls CLI arguments.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The memory manager persists user-provided memory content to disk via save() without any explicit user-facing disclosure, consent flow, or indication that entries are durably stored. In an agent skill context, users may assume 'memory' is transient or session-scoped, so silently writing potentially sensitive prompts, notes, or secrets to local files creates a privacy and data-retention risk.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
syncToMarkdown() exports the full contents of all memories, including tags, timestamps, and raw content, into a markdown file on every save. This broadens exposure beyond the primary JSON store, increases the number of copies of sensitive data, and does so automatically without explicit disclosure or user approval.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
This code returns natural-language strings in Chinese for decay warnings and critical-state alerts. Because the file does not indicate that the skill is China/Chinese-specific or provide any user opt-in for language selection, it violates the policy against forcing a specific language or locale.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The trigger list includes common conversational phrases such as "记录", "记住", "找找之前", and "我的记忆", which are broad enough to activate during normal user dialogue rather than explicit tool invocation. In an agent skill context, this can cause unintended execution of memory operations, accidental data capture, or interference with other skills, making it a real safety issue even though it is not inherently malicious.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The export functionality writes the full in-memory dataset, including raw memory content, directly to files in the current working directory without any confirmation, redaction option, or warning about sensitive data exposure. In a memory-management skill, those records are likely to contain personal, confidential, or operationally sensitive information, so accidental export to an insecure location can create a meaningful confidentiality risk.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The function returns natural-language user messages in Chinese only, which forces a specific language on users regardless of their locale or preference. This matches the policy-violation category for language or locale constraints without user opt-in.

Missing User Warnings

Low
Confidence
81% confidence
Finding
This code launches a child process via execSync and inherits its stdio, but there is no confirmation prompt, user-facing disclosure, or explanatory comment warning that a subprocess will be executed. For a code file, subprocess execution is a safety-relevant operation that should be disclosed unless clearly communicated as part of the skill's stated purpose within the file or accompanying markdown.

Natural-Language Policy Violations

Low
Confidence
90% confidence
Finding
This code file contains a natural-language comment in Chinese ('防御性检查:确保 strength.score 是有效数字') while the rest of the file is in English. A mixed-language instruction/comment can violate language policy if the skill implicitly forces a specific language or locale without offering user choice or documenting the constraint.

Vague Triggers

Low
Confidence
78% confidence
Finding
This .txt file is in scope for vague-trigger checks, but it only enumerates repository files and provides no information about how or when the skill should activate. Without explicit trigger phrases, boundaries, or exclusions, the activation condition is underspecified from this artifact alone.

Unpinned Dependencies

Low
Category
Supply Chain
Content
]
  },
  "devDependencies": {
    "@types/node": "^25.5.2",
    "typescript": "^6.0.2"
  }
}
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
},
  "devDependencies": {
    "@types/node": "^25.5.2",
    "typescript": "^6.0.2"
  }
}
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Natural-Language Policy Violations

Low
Confidence
91% confidence
Finding
The inline comment at L040 is written in Chinese while the rest of the file is in English, creating an implicit language constraint for maintainers and reviewers. This is a natural-language policy concern because the file does not offer a language choice or document a justified locale-specific requirement.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
The inline comment at L040 is written only in Chinese, creating a language-specific constraint in the skill source without offering any user or maintainer language choice. This can violate language/locale policy expectations when the rest of the file is in English and no opt-in or justification is provided.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The removeLinksForMemory method deletes link records and immediately saves the modified dataset, which is a destructive operation. In this file there is no confirmation prompt, user-facing warning, or explanatory comment/docstring disclosing that the deletion is persisted.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
The code contains developer-facing natural-language comments in Chinese only (for example, '正则模式', '模糊模式', and '按相关性排序'). This imposes a specific language choice in the file's instructions/comments without offering an alternative or documenting a justified locale constraint.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
This TypeScript file contains multiple natural-language comments and docstrings in Chinese, such as the section header at L095 and function documentation through L219. Under the policy rule for language/locale, this is a forced language choice with no indication of user opt-in or a documented region-specific justification.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
This JSON file contains natural-language content in Chinese, and there is no accompanying indication that the language was user-selected or that the skill is intentionally region-specific. Per the policy, forcing a specific language or locale without opt-in can be a natural-language policy issue.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
This JSON file contains natural-language content in Chinese, and there is no accompanying indication that the language was user-selected or that the skill is intentionally region-specific. Per the policy, forcing a specific language or locale without opt-in can be a natural-language policy issue.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
This JSON file contains natural-language content in Chinese, and there is no accompanying indication that the language was user-selected or that the skill is intentionally region-specific. Per the policy, forcing a specific language or locale without opt-in can be a natural-language policy issue.

Natural-Language Policy Violations

Low
Confidence
81% confidence
Finding
This JSON file contains natural-language content in Chinese, and there is no accompanying indication that the language was user-selected or that the skill is intentionally region-specific. Per the policy, forcing a specific language or locale without opt-in can be a natural-language policy issue.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
bin/memory.js:21