Back to skill

Security audit

Memoria

Security checks for vulnerabilities and agentic risk

Overview

Memoria is a real memory and Notion-sync tool, but it over-collects sensitive conversation data, auto-syncs it, and has filesystem and token-handling weaknesses users should review carefully.

Install only if you are comfortable with an agent persistently recording conversation details and possibly syncing them to a user-configured Notion workspace. Before use, remove the proactive capture guidance, avoid storing secrets, health data, and third-party personal details, keep Notion auto-sync off unless explicitly needed, rotate any token entered on the command line, and fix the vault path validation issue.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • 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)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:36
Finding
Proactive collection and automatic export of sensitive conversational data<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:21-32`, `SKILL.md:36-61`, `SKILL.md:98`; `src/commands/setup-notion.ts:25-32`; `src/lib/auto-sync.ts:8-18`; `src/lib/notion-sync.ts:43-111` **Vulnerability Type**: Agent instruction hijacking and excessive sensitive-data collection **Risk Level**: High ### Vulnerable Code and Instructions `SKILL.md:21-32`: ```markdown Run at the start and end of every session: ```bash memoria wake # start session, restore context memoria checkpoint --working-on "<task>" # mid-session save memoria sleep "<summary>" --next "<next steps>" # end session, write handoff ``` ## Storing Memories ```bash memoria remember <type> "<title>" --content "<details>" memoria sync --push # always sync after storing ``` ``` `SKILL.md:36-61`: ```markdown ### What to capture (proactively, without being asked) | Signal | Type | |--------|------| | Human shares personal info (name, location, health, settings) | `fact` | | A decision is made with reasoning | `decision` | | Human says "I prefer / always / never..." | `preference` | | An insight or lesson emerges | `lesson` | | A promise, goal, or deadline is set | `commitment` | | A person is mentioned with context | `relationship` | | An ongoing project is discussed | `project` | **If in doubt, store it.** Better to have a memory you never look up than to forget something. ### Proactive capture triggers Listen for these patterns and store immediately: - "I always...", "I never...", "I prefer..." -> `preference` - "Let's go with...", "We decided...", "The plan is..." -> `decision` - "I learned that...", "Turns out...", "The trick is..." -> `lesson` - "My name is...", "I take...", "I live in...", "I work at..." -> `fact` - "I need to...", "I promised...", "By next week..." -> `commitment` - "Talk to Alice about...", "Bob said..." -> `relationship` - "We're building...", "The project ...[truncated 3727 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove instructions to collect information “without being asked” and remove the “If in doubt, store it” policy. 2. Require explicit user consent before storing personal, health, credential-related, relationship, or third-party information. 3. Ask separately whether the user authorizes remote synchronization of sensitive memories. 4. Keep `autoSync` disabled by default after Notion setup and require an explicit opt-in operation to enable it. 5. Display the exact documents and destination before the first upload. 6. Add per-category synchronization controls and exclude sensitive categories by default. 7. Support local-only records that cannot be uploaded even during a bulk synchronization. 8. Provide commands to inspect, redact, export, and permanently delete stored information. 9. Document retention periods and the security implications of storing information in Notion. 10. Avoid imposing mandatory wake, checkpoint, sleep, or synchronization behavior on unrelated sessions. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
src/lib/vault.ts:50
Finding
Path traversal allows Markdown file access outside the configured vault<![CDATA[ ## Vulnerability Details **File Location**: `src/lib/vault.ts:50-79`, `src/lib/vault.ts:84-96`, `src/lib/vault.ts:98-127`; exposed through `src/commands/store.ts:5-23` and `src/cli/index.ts:28-35`, `src/cli/index.ts:52-61` **Vulnerability Type**: Path traversal and missing vault-boundary validation **Risk Level**: High ### Vulnerable Code `src/lib/vault.ts:50-79`: ```ts export async function storeDocument( vaultPath: string, options: StoreOptions, ): Promise<MemDocument> { const slug = slugify(options.title); const filePath = join(vaultPath, options.category, `${slug}.md`); const relPath = relative(vaultPath, filePath); if (!options.overwrite) { let exists = false; try { await stat(filePath); exists = true; } catch { // file does not exist, safe to write } if (exists) { throw new Error(`Document already exists: ${relPath}. Use --overwrite to replace.`); } } const raw = serializeDocument({ title: options.title, content: options.content, frontmatter: options.frontmatter, tags: options.frontmatter?.tags as string[] | undefined, }); await mkdir(dirname(filePath), { recursive: true }); await writeFile(filePath, raw, 'utf-8'); return parseDocument(raw, relPath, options.category); } ``` `src/lib/vault.ts:84-96`: ```ts export async function getDocument( vaultPath: string, id: string, ): Promise<MemDocument> { let filePath = join(vaultPath, id); if (extname(filePath) !== '.md') filePath += '.md'; const raw = await readFile(filePath, 'utf-8'); const parts = relative(vaultPath, filePath).split('/'); const category = parts.length > 1 ? parts[0] : 'inbox'; return parseDocument(raw, relative(vaultPath, filePath), category); } ``` `src/lib/vault.ts:98-127`: ```ts export async function listDocuments( vaultPath: string, category?: string, ): Promise<MemDocument[]> { const config = await readConfig(vaultPath); const categories = category ? [categ ...[truncated 4100 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Canonicalize the vault root and every candidate path with `path.resolve`. 2. Require the candidate path to equal the vault root or begin with `vaultRoot + path.sep`. 3. Reject absolute paths, `.` segments, `..` segments, null bytes, and platform-specific path separators in category and ID inputs. 4. Restrict categories to values present in `config.categories`. 5. Restrict document IDs to a strict format such as `^[a-z0-9-]+/[a-z0-9-]+$`. 6. Apply the same validation to store, get, list, search, delete, synchronization, and session paths. 7. Consider resolving parent directories with `realpath` to prevent symlink-based vault escape. 8. Refuse to follow symlinks when opening vault documents where the runtime and platform permit it. 9. Add automated tests covering: - `../` traversal - Nested traversal - Absolute paths - Windows drive and UNC paths - Encoded or mixed path separators - Symlink escapes - Overwrite attempts outside the vault 10. Return a clear validation error instead of silently ignoring invalid external directories. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
src/lib/config.ts:16
Finding
Notion bearer token is accepted on the command line and persisted in plaintext<![CDATA[ ## Vulnerability Details **File Location**: `src/types.ts:1-13`, `src/commands/setup-notion.ts:6-32`, `src/lib/config.ts:16-19`, `src/cli/index.ts:98-104` **Vulnerability Type**: Insecure credential handling and plaintext secret storage **Risk Level**: Medium ### Vulnerable Code `src/types.ts:1-13`: ```ts export interface VaultConfig { path: string; name: string; categories: string[]; autoSync?: boolean; notion?: NotionConfig; } export interface NotionConfig { token: string; rootPageId: string; databases?: Record<string, string>; } ``` `src/commands/setup-notion.ts:6-32`: ```ts export async function setupNotionCommand( options: { token: string; page: string; vault?: string }, ): Promise<void> { if (!options.token || !options.page) { console.log(chalk.red('Both --token and --page are required.')); console.log(chalk.dim('Usage: memoria setup-notion --token <token> --page <root-page-id>')); process.exit(1); } const config = await resolveVault(options.vault); const client = createNotionClient(options.token); try { await client.pages.retrieve({ page_id: options.page }); } catch (err) { console.log(chalk.red('Failed to access Notion page. Check your token and page ID.')); console.log(chalk.dim(err instanceof Error ? err.message : String(err))); process.exit(1); } config.notion = { token: options.token, rootPageId: options.page, }; config.autoSync = true; await writeConfig(config); ``` `src/lib/config.ts:16-19`: ```ts export async function writeConfig(config: VaultConfig): Promise<void> { const filePath = configPath(config.path); await writeFile(filePath, JSON.stringify(config, null, 2) + '\n', 'utf-8'); } ``` `src/cli/index.ts:98-104`: ```ts program .command('setup-notion') .description('Configure Notion integration') .requiredOption('--token <token>', 'Notion integration token') .requiredOption('--page <pageId>', 'Root Notion page ID') .option('-v, --vau ...[truncated 2178 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not accept bearer tokens directly as ordinary command-line arguments. 2. Read the token from a protected environment variable, standard input without echo, an OS credential manager, or a dedicated secrets service. 3. Store only a credential reference in `.memoria.json`, not the token itself. 4. If local file storage is unavoidable: - Create the secret file with mode `0600`. - Verify file ownership before reading or writing. - Refuse to use a file that is group-readable or world-readable. - Keep secrets in a separate file outside the document vault. 5. Add `.memoria.json` or the replacement secret file to generated ignore rules and clearly warn users against committing it. 6. Redact tokens from errors, diagnostics, telemetry, command previews, and logs. 7. Provide token rotation and revocation instructions. 8. Minimize Notion integration permissions and share only the dedicated Memoria root page. 9. Add tests that verify restrictive permissions and ensure secrets are absent from ordinary configuration serialization. ]]>
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
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
Findings (46)

Missing User Warnings

High
Confidence
94% confidence
Finding
The skill enables automatic Notion sync after storing memories but does not prominently warn that user data will be transmitted to a third-party service. Because this skill is designed to persist user memories, silent or default remote transmission materially increases confidentiality and compliance risk.

Ssd 3

High
Confidence
98% confidence
Finding
These agent instructions direct proactive capture of sensitive personal information, including health and personal details, and then instruct syncing after storage. That combination of unsolicited persistence plus outbound transfer creates a substantial privacy and data-handling vulnerability, especially because the agent is told not to wait to be asked.

Missing User Warnings

High
Confidence
96% confidence
Finding
The instructions explicitly encourage storing highly sensitive user data such as health details and personal facts without any consent, minimization, retention, or privacy warning. In a memory skill with persistence and optional remote sync, this creates a real risk of collecting protected or intimate information beyond user expectations and exposing it to later misuse or leakage.

Ssd 3

High
Confidence
97% confidence
Finding
The proactive capture triggers operationalize automatic logging of sensitive user statements into persistent memory from normal conversation. In the context of a long-term memory system, this is especially dangerous because it scales inadvertent surveillance-like retention across many interactions and can create durable privacy harm if exposed or synced externally.

Missing User Warnings

High
Confidence
98% confidence
Finding
The README explicitly tells agents to store highly sensitive categories of user information, including health data and credential-related context, without requiring user consent, minimization, or exclusions for secrets. In a memory skill that also supports Notion synchronization, this creates a clear risk of persistent retention and third-party propagation of sensitive data beyond the immediate conversation.

Ssd 3

High
Confidence
99% confidence
Finding
This skill is specifically designed as a structured memory system with local retention and two-way Notion sync, so instructions to retain facts about health, relationships, preferences, and credential-related context materially increase privacy and security risk. The combination of indiscriminate retention plus automatic external sync can lead to unauthorized long-term storage, broader exposure, and accidental disclosure of sensitive user information.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The supplied code chunk does not implement a structured memory system. It only parses Markdown into Notion block request objects and serializes Notion-style blocks back into Markdown. While this could be a supporting utility for a larger Notion sync feature, in isolation its actual behavior is a text/block conversion helper, not memory storage, retrieval, search, session management, or synchronization. Therefore the declared description does not accurately represent what this code chunk actually does.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description describes a full memory-management skill with storage, retrieval, session controls, and Notion sync. The provided code chunk does none of that; it only configures the Vitest test runner by setting globals to true and specifying which test files to include. This is a materially different primary purpose and is unrelated to the declared functionality.

Vague Triggers

High
Confidence
97% confidence
Finding
The skill is designed to activate on very broad signals such as any user desire to store, recall, search, or share important information, and then encourages proactive capture. In a memory skill, this context makes over-triggering particularly dangerous because unintended activation can lead to silent retention of personal or sensitive data beyond the user's expectations.

Missing User Warnings

High
Confidence
99% confidence
Finding
The skill explicitly tells the agent to capture personal information such as name, location, health, and work details proactively and says 'If in doubt, store it' without any warning, consent flow, retention notice, or privacy constraints. This is dangerous because it normalizes collection of sensitive data without informed user approval and can create persistent privacy harm if retained or later exposed.

Ssd 3

High
Confidence
99% confidence
Finding
The instructions direct proactive collection and retention of personal and potentially sensitive user information without requiring an explicit request from the user. In the context of a memory skill, this materially increases the risk of over-collection, long-term retention, and secondary disclosure of sensitive data that the user never intended to persist.

Ssd 3

High
Confidence
99% confidence
Finding
The pattern-matching triggers instruct immediate storage when users mention phrases like 'My name is...', 'I take...', or 'I live in...', which can include highly sensitive data such as health and location. This is dangerous because the automation bypasses deliberation and consent, making it easy to persist sensitive disclosures the moment they are uttered.

Known Vulnerable Dependency: brace-expansion==2.0.2 — 4 advisory(ies): CVE-2026-13149 (brace-expansion: DoS via exponential-time expansion of consecutive non-expanding); CVE-2026-33750 (brace-expansion: Zero-step sequence causes process hang and memory exhaustion); CVE-2026-14257 (brace-expansion: DoS via unbounded expansion length causing an out-of-memory pro) +1 more

High
Category
Supply Chain
Confidence
94% confidence
Finding
brace-expansion 2.0.2 is a real supply-chain risk because known DoS issues in brace parsing/expansion can be triggered by attacker-controlled glob-like patterns. In this lockfile it is only a transitive dependency, but if the skill accepts user-controlled patterns or file selectors through glob/minimatch flows, this can cause CPU or memory exhaustion rather than direct code execution.

Known Vulnerable Dependency: form-data==4.0.5 — 1 advisory(ies): CVE-2026-12143 (form-data: CRLF injection in form-data via unescaped multipart field names and f)

High
Category
Supply Chain
Confidence
89% confidence
Finding
form-data 4.0.5 has a CRLF injection issue in multipart field names, which can corrupt HTTP multipart requests or enable header/body manipulation when attacker-controlled names are used. Here it is transitively pulled by @types/node-fetch rather than obviously used directly, so exploitability in this skill is limited but the vulnerable package is genuinely present.

Known Vulnerable Dependency: js-yaml==3.14.2 — 4 advisory(ies): CVE-2026-84375 (js-yaml: maxTotalMergeKeys does not limit CPU use for empty merge sources); CVE-2026-59869 (js-yaml: YAML merge-key chains can force quadratic CPU consumption); GHSA-5p4m-2wfm-xmqj (JS-YAML: Quadratic CPU consumption in !!omap resolution (3.x and 4.x) — CVE-2026) +1 more

High
Category
Supply Chain
Confidence
95% confidence
Finding
js-yaml 3.14.2 has multiple CPU-exhaustion issues involving crafted YAML structures such as merge keys and omap handling. Because this skill includes gray-matter, which commonly parses front matter from Markdown files, hostile memory documents or synced content could realistically trigger parser-level denial of service.

Known Vulnerable Dependency: minimatch==9.0.5 — 3 advisory(ies): CVE-2026-27904 (minimatch ReDoS: nested *() extglobs generate catastrophically backtracking regu); CVE-2026-26996 (minimatch has a ReDoS via repeated wildcards with non-matching literal in patter); CVE-2026-27903 (minimatch has ReDoS: matchOne() combinatorial backtracking via multiple non-adja)

High
Category
Supply Chain
Confidence
94% confidence
Finding
minimatch 9.0.5 has known ReDoS/backtracking issues that can be triggered with malicious glob patterns. This matters in a memory-management skill because file discovery and search features often accept path or pattern input, making denial of service plausible if untrusted patterns are processed.

Known Vulnerable Dependency: nanoid==3.3.11 — 3 advisory(ies): CVE-2026-67214 (nanoid: non-secure generators can loop indefinitely with negative size); CVE-2026-67213 (nanoid: custom generators can loop indefinitely when size is zero); CVE-2026-73086 (nanoid: Integer Overflow or Wraparound)

High
Category
Supply Chain
Confidence
83% confidence
Finding
nanoid 3.3.11 has reported issues that can lead to infinite loops or integer-related failures in edge cases such as invalid size values or custom generators. In this lockfile it is a dev/transitive dependency under postcss, so it is a real vulnerable component but unlikely to affect runtime behavior of the skill unless build tooling processes attacker-controlled inputs.

Known Vulnerable Dependency: picomatch==4.0.3 — 2 advisory(ies): CVE-2026-33672 (Picomatch: Method Injection in POSIX Character Classes causes incorrect Glob Mat); CVE-2026-33671 (Picomatch has a ReDoS vulnerability via extglob quantifiers)

High
Category
Supply Chain
Confidence
86% confidence
Finding
picomatch 4.0.3 has known issues including ReDoS and incorrect matching via method injection in POSIX character classes. Here it appears only in dev tooling paths, so the package itself is vulnerable, but exploitation against end users of the skill is less likely unless untrusted glob patterns are handled during build/test workflows.

Known Vulnerable Dependency: postcss==8.5.6 — 4 advisory(ies): CVE-2026-45623 (PostCSS: Arbitrary file read and information disclosure via attacker-controlled ); CVE-2026-69153 (PostCSS: incomplete fix of GHSA-6g55-p6wh-862q — attacker-controlled sourceMappi); CVE-2026-41305 (PostCSS has XSS via Unescaped </style> in its CSS Stringify Output) +1 more

High
Category
Supply Chain
Confidence
84% confidence
Finding
postcss 8.5.6 has reported issues including arbitrary file read and output-encoding problems in specific processing scenarios. In this lockfile it is a dev dependency used by vite/tsup-related tooling, so it is a genuine vulnerable component, but there is limited evidence that the skill runtime exposes CSS processing to attackers.

Known Vulnerable Dependency: rollup==4.58.0 — 1 advisory(ies): CVE-2026-27606 (Rollup 4 has Arbitrary File Write via Path Traversal)

High
Category
Supply Chain
Confidence
80% confidence
Finding
rollup 4.58.0 has a reported arbitrary file write/path traversal issue, which is serious when untrusted archives, plugin inputs, or output paths are handled by the bundler. In this case rollup is present in dev tooling, so the vulnerable package is real, but exposure depends on whether builds consume attacker-controlled project content or plugin configuration.

Memory Manipulation

High
Category
Memory Poisoning
Content
}

export function removeEntry(state: SyncState, localPath: string): void {
  delete state.entries[localPath];
}
Confidence
80% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The instruction 'If in doubt whether something is worth storing, store it' removes any meaningful boundary on collection and pushes the agent toward over-retention. In a memory product, this broad default encourages storage of incidental, unnecessary, and potentially sensitive information that the user did not intend to persist.

Vague Triggers

Medium
Confidence
92% confidence
Finding
The trigger phrases map common conversational statements directly into persistent memory categories, which makes accidental collection likely during ordinary dialogue. Because these patterns include personal identity, relationships, commitments, and preferences, they can cause the agent to persist context users may have shared only transiently.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
The instructions encourage blanket collection with phrases like 'Store important information immediately,' 'After storing, always sync,' and 'If in doubt whether something is worth storing, store it.' That removes meaningful sensitivity filtering and opt-in, making overcollection likely and causing agents to persist user data that should remain ephemeral.

Lp3

Medium
Category
MCP Least Privilege
Confidence
82% confidence
Finding
The skill instructs use of shell commands and environment variables (`export MEMORIA_VAULT=~/memory`) but does not declare an explicit tool scope or allowed-tools boundary. That increases the risk that an agent may execute commands or modify environment state without clear authorization or review, especially in frameworks that rely on manifest scoping for safety.

Static analysis

No suspicious patterns detected.