Back to skill

Security audit

getmem.ai Memory

Security checks for vulnerabilities and agentic risk

Overview

This memory plugin does what it advertises, but it automatically sends and stores conversations with a third-party service and reinserts that data later without enough controls.

Install only in workspaces where users and administrators explicitly accept that prompts, replies, and user identifiers will be sent to and stored by getmem.ai. Avoid sensitive, regulated, or multi-tenant deployments until there are clear opt-in controls, deletion and retention controls, stronger identity scoping, safer memory injection, and pinned necessary dependencies.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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 (4)

T02 · Agent Memory Poisoning

Error
Location
src/index.ts:75
Finding

Persistent Memory Content Is Injected into the Agent Prompt Without Trust Boundaries

Content
View full analysis
{ const ctx = event.context; const from = (ctx["from"] as string) ?? "unknown"; const userId = rawId(from); const userMessage = (ctx["content"] as string) ?? ""; // Store under raw ID for lookup in message:sent lastMessage.set(userId, userMessage); try { const result = await mem.get(userId, userMessage); if (result.context?.trim()) { event.messages.push(`[Memory]\n${result.context}`); } } catch (err) { api.logger.warn(`[getmem] fetch failed: ${(err as Error).message}`); } }, { name: "getmem-message-received" }); ``` The corresponding compiled implementation is present in `dist/index.js:57-78`. ### Technical Analysis The plugin retrieves persistent memory from an external service and appends the returned text directly to `event.messages`. The returned context is not escaped, filtered, assigned a constrained data-only role, or accompanied by a reliable instruction that it must not be treated as executable agent guidance. Because ordinary user messages are uploaded to the same memory service, instruction-like content supplied by a user may later be retrieved and reintroduced into subsequent prompts. This turns untrusted conversation content into a persistent prompt-injection channel. The `[Memory]` prefix is only a textual label. It does not enforce a privilege boundary between memory data and agent instructions. ### Attack Path 1. An attacker sends a message containing instruction-like content designed to alter future agent behavior. 2. After the assistant responds, the plugin uploads the attacker-controlled message through `/v1/memory/ingest`. 3. During a later message, `/v1/memory/get` returns that stored content as relevant context. 4 ...[truncated 848 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/index.ts:47
Finding

Loss of Channel and Session Scope Can Cause Cross-User Memory Collisions

Content
View full analysis
(); ``` ```ts api.registerHook("message:received", async (event: InternalHookEvent) => { const ctx = event.context; const from = (ctx["from"] as string) ?? "unknown"; const userId = rawId(from); const userMessage = (ctx["content"] as string) ?? ""; // Store under raw ID for lookup in message:sent lastMessage.set(userId, userMessage); ``` ```ts api.registerHook("message:sent", async (event: InternalHookEvent) => { const ctx = event.context; if (!ctx["success"]) return; const assistantContent = (ctx["content"] as string) ?? ""; if (assistantContent.includes("⚠️") || !assistantContent.trim()) return; // Extract raw user ID from session key: "agent:main:telegram:direct:USERID" const sessionParts = event.sessionKey.split(":"); const userId = rawId(sessionParts[sessionParts.length - 1] ?? "unknown"); const userMessage = lastMessage.get(userId) ?? ""; if (!userMessage) return; void mem.ingest(userId, userMessage, assistantContent).catch( (err: Error) => api.logger.warn(`[getmem] ingest failed: ${err.message}`) ); }, { name: "getmem-message-sent" }); ``` The corresponding compiled implementation is present in `dist/index.js:43-46, 57-94`. ### Technical Analysis The `rawId` function removes all channel and namespace information and retains only the final colon-separated component. Distinct principals such as `telegram:123` and `discord:123` therefore become the same memory identity, `123`. The global `lastMessage` map is also keyed only by this redu ...[truncated 1567 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
src/index.ts:11
Finding

Unrestricted API Base URL Can Expose Credentials and Conversation Data

Content
View full analysis
(path: string, body: unknown): Promise { const res = await fetch(`${this.baseUrl}${path}`, { method: "POST", headers: { Authorization: `Bearer ${this.apiKey}`, "Content-Type": "application/json" }, body: JSON.stringify(body), }); if (!res.ok) throw new Error(`getmem ${res.status}: ${res.statusText}`); return res.json() as Promise; } ``` The endpoint is also exposed as an unrestricted string in `openclaw.plugin.json:14-18`. ### Technical Analysis The schema verifies only that `baseUrl` is syntactically a URL. It does not require HTTPS or restrict the destination host. Every request to the configured endpoint includes the getmem bearer API key and sensitive message content. If configuration is modified maliciously or set incorrectly, the plugin will transmit its credential, sender identifiers, user messages, and assistant replies to an arbitrary server. An `http://` URL also permits cleartext interception and modification on the network. Depending on the runtime's network access, an arbitrary endpoint could additionally be used to make requests to internal HTTP services, although the fixed POST paths and headers constrain that scenario. ### Attack Path 1. An attacker with the ability to modify plugin configuration changes `baseUrl` to an attacker-controlled URL, or an administrator accidentally configures an unt ...[truncated 875 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
package.json:22
Finding

Unused and Inconsistently Declared Third-Party Packages Increase Supply-Chain Exposure

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • 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
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (20)

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

This plugin transmits both user messages and assistant replies to an external third-party memory service via the ingest endpoint, but the code contains no user notice, consent flow, opt-in gating per user, or filtering for sensitive content. Because the plugin is explicitly designed to persist conversations for every user, it can exfiltrate personal, confidential, or regulated data from chats to an external provider without participants understanding or approving that transfer.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

On every inbound message, the plugin sends the user's content to an external memory lookup service before the agent responds, again without any warning or consent mechanism in this code. This is especially risky because even a first message from a user is transmitted off-platform immediately, which can expose sensitive prompts, identifiers, or private information and also inject untrusted third-party context back into the agent conversation.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The plugin sends both user messages and assistant replies to an external service and reinjects retrieved memory into future prompts, but this file contains no consent, notice, opt-in-by-user, data minimization, or per-channel privacy gating. In a conversational agent context, that can expose sensitive user content to a third party and create compliance, privacy, and confidentiality risks, especially because the behavior is automatic for every message.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code stores and transmits complete conversational exchanges to a third-party persistence service, creating a durable external record of potentially sensitive user data. This materially increases exposure in the event of provider compromise, misconfiguration, regulatory noncompliance, or unintended retention beyond user expectations.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README explicitly markets persistent memory that automatically ingests conversations for every user, but it does not prominently warn operators that user messages and conversation history are transmitted to a third-party service and stored over time. This creates a real privacy and compliance risk because deployers may enable it without obtaining consent, updating disclosures, or restricting sensitive data flows.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README describes two external API calls that send the sender's user ID, message content, and the full exchange to a remote memory service, including automatic prompt injection of retrieved memory, but it omits an explicit safety/privacy warning. In the context of an agent plugin, this is more dangerous because the behavior is automatic, persistent, and applies to every conversation, increasing the chance of silent exfiltration of personal, confidential, or regulated data.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding

The skill advertises behavior that requires outbound network access to getmem.ai, but it does not declare an explicit tool scope such as permissions or allowed-tools. That mismatch weakens operator visibility and policy enforcement, increasing the chance that users install a skill with data-exfiltrating capabilities they did not explicitly approve.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill states that it automatically fetches memory before each reply and ingests exchanges after each reply, which means conversation content is continuously transmitted to a third-party service. Without a prominent privacy warning and informed consent language, users may unknowingly expose sensitive prompts, personal data, credentials, or proprietary information to an external provider.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The stated design is to persist user data across sessions and resurface it later, which creates a durable retention mechanism for plain-language content that may include secrets, personal data, or regulated information. Even if this is the product's intended feature, retaining and later replaying prior content increases the blast radius of any disclosure, misuse, or over-collection.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The plugin automatically retrieves prior memory based on the current message and appends the recalled text directly into the prompt. This can reintroduce stale, sensitive, or attacker-planted content into the model context, enabling privacy leaks, prompt injection persistence, and unintended influence over future responses.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

After each successful exchange, the plugin uploads both user and assistant content to persistent external memory automatically. This broad, continuous ingestion can capture sensitive user disclosures and model outputs containing confidential data, creating long-lived third-party exposure and making future resurfacing of that content more likely.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The description advertises automatic, persistent memory across sessions in broad terms without indicating any user consent, scope limitation, or control boundary. In a memory plugin, this increases the risk of silent collection and reuse of sensitive conversational data, which can create privacy, compliance, and data-handling issues if deployed as described.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The plugin sends each inbound user message to an external API for memory lookup before the agent responds, again without visible notice or consent controls in this code. Even if used for contextual recall, transmitting raw prompts to a third party can leak sensitive user data and create compliance risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The plugin persistently sends full user and assistant messages to an external service, but this file shows no consent, notice, opt-in, or data minimization controls. In a memory plugin this behavior is expected functionally, but it is still privacy-sensitive and can expose personal or confidential content to a third party without adequate transparency.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The plugin normalizes identities by stripping channel prefixes and then uses the raw ID as the sole memory key. If different platforms or contexts reuse the same identifier value, their conversations can be merged, causing cross-user or cross-channel data disclosure and contamination of memory retrieval.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The plugin injects externally retrieved memory directly into the prompt stream, which can resurface old sensitive data and influence future model outputs. If memory entries are overbroad, stale, or contaminated by identity collisions, the model may disclose private information to the wrong conversation or act on attacker-planted memory content.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
81% confidence
Finding

Stating that the plugin provides persistent memory for every user implies universal storage of user data without mentioning consent, policy controls, or jurisdiction-specific handling. Given the skill context is a memory service that automatically remembers users across sessions, this omission makes the privacy risk more credible rather than merely theoretical.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
89% confidence
Finding

The runtime dependency getmem-ai is specified with a caret range, which allows newer published versions to be installed without review. If the upstream package is compromised, typo-squatted, or releases a malicious update, this skill would automatically consume it in future installs, creating a supply-chain risk. The skill context increases concern because it handles persistent memory and likely processes sensitive conversation data.

Content

Scanner excerpt · package.json (reported line 26)May include surrounding context.

json
"typecheck": "tsc --noEmit"
  },
  "dependencies": {
    "getmem-ai": "^0.0.1"
  },
  "devDependencies": {
    "typescript": "^5.4.0"

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
77% confidence
Finding

The typescript devDependency is also specified with a caret range, permitting unreviewed compiler updates to be pulled in during development or CI. This is a weaker risk than an unpinned runtime dependency because it does not ship directly in production, but a compromised build-time tool can still affect generated artifacts or CI environments.

Content

Scanner excerpt · package.json (reported line 29)May include surrounding context.

json
"getmem-ai": "^0.0.1"
  },
  "devDependencies": {
    "typescript": "^5.4.0"
  },
  "keywords": [
    "openclaw",

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
82% confidence
Finding

The inline documentation says the session key format is "agent:main:telegram:direct:USERID" and implies the last segment is the user ID. The actual code does not validate that format and blindly uses the final segment from any sessionKey, so the comment overstates what the code guarantees and can mislead maintainers about identity extraction semantics.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.