Back to skill

Security audit

Honcho Memory Multiplexer

Security checks for vulnerabilities and agentic risk

Overview

This memory skill is broadly purpose-aligned, but it automatically sends conversation content to Honcho and injects stored memory into future prompts without enough disclosure or user control.

Install only if you are comfortable with Honcho receiving and retaining conversation memory, including potentially sensitive prompts and assistant responses. Prefer a self-hosted or explicitly approved endpoint, review all instruction-file edits before applying them, avoid using it in sessions with secrets unless capture can be disabled or redacted, and ask the publisher for clearer opt-in, deletion, retention, and prompt-injection safeguards.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
extension/index.ts:183
Finding
Automatic Upload of Complete Conversations to an External Honcho Service<![CDATA[ ## Vulnerability Details **File Location**: `extension/index.ts:183-221` **Vulnerability Type**: Sensitive data exposure through automatic network transmission **Risk Level**: High ### Vulnerable Code ```typescript // ======================================================================== // HOOK: agent_end — persist messages to Honcho // (local files are written by the agent via normal tool calls) // ======================================================================== api.on("agent_end", async (event: any, ctx: any) => { if (!event.success || !event.messages?.length) return; const sessionKey = buildSessionKey(ctx); try { await ensureInitialized(); const session = await honcho.session(sessionKey, { metadata: {} }); let meta = await session.getMetadata(); if (meta.lastSavedIndex === undefined) { const startIndex = Math.max(0, event.messages.length - 2); await session.setMetadata({ lastSavedIndex: startIndex }); meta = { lastSavedIndex: startIndex }; } const lastSaved = meta.lastSavedIndex ?? 0; await session.addPeers([ [OWNER_ID, { observe_me: true, observe_others: false }], [OPENCLAW_ID, { observe_me: false, observe_others: true }], ]); if (event.messages.length <= lastSaved) return; const newMessages = extractMessages( event.messages.slice(lastSaved), ownerPeer, openclawPeer ); if (newMessages.length > 0) { await session.addMessages(newMessages); } await session.setMetadata({ ...meta, lastSavedIndex: event.messages.length }); } catch (err) { api.logger.error(`[mux] Failed to save to Honcho: ${err}`); } }); ``` The network destination defaults to a managed external service: ```typescript baseUrl: (pluginConfig.baseUrl as string) || "https://api.honcho.dev", ``` ### Technical Analysis The `agent_end` hook automatically extracts all newly observed user and assistant text from every successful conversation and tr ...[truncated 2317 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable automatic conversation upload by default and require explicit, informed opt-in. 2. Display the effective destination, including whether it is managed or self-hosted, before enabling capture. 3. Add per-session privacy controls and allow users to exclude individual messages or entire sessions. 4. Implement an allowlist-based capture policy so only explicitly selected durable facts are uploaded. 5. Detect and redact common secret formats, including API keys, bearer tokens, passwords, private keys, and credentials. 6. Provide configurable retention and deletion controls for previously uploaded messages. 7. Accurately declare managed Honcho network access in `SKILL.md`, not only self-hosted access. 8. Require HTTPS for non-loopback destinations and warn before accepting untrusted custom endpoints. 9. Record an auditable upload manifest that identifies what was sent, when, and to which endpoint without duplicating the sensitive content. 10. Consider processing and storing local memory by default, with remote synchronization implemented as a separate explicit action. ]]>

T01 · Skill Instruction Hijacking

Error
Location
extension/index.ts:151
Finding
Untrusted Remote Memory Injected into the Privileged System Prompt<![CDATA[ ## Vulnerability Details **File Location**: `extension/index.ts:151-176` **Vulnerability Type**: Persistent indirect prompt injection through retrieved memory **Risk Level**: High ### Vulnerable Code ```typescript let context: any; try { context = await (session as any).context({ summary: true, tokens: 2000, peerTarget: ownerPeer, peerPerspective: openclawPeer, }); } catch (e: any) { if (e?.message?.toLowerCase().includes("not found")) return; throw e; } const sections: string[] = []; if (context.peerCard?.length) sections.push(`Key facts:\n${context.peerCard.map((f: string) => `• ${f}`).join("\n")}`); if (context.peerRepresentation) sections.push(`User context:\n${context.peerRepresentation}`); if (context.summary?.content) sections.push(`Earlier in this conversation:\n${context.summary.content}`); if (!sections.length) return; return { systemPrompt: `## User Memory Context\n\n${sections.join("\n\n")}\n\nUse this context naturally when relevant.`, }; ``` ### Technical Analysis The extension retrieves free-form content from Honcho and concatenates it directly into the agent's system prompt. The retrieved values can originate from previously captured user messages, migrated memory, generated summaries, peer representations, or facts derived by the remote service. No trust boundary separates factual memory from executable instructions. The injected system prompt does not tell the model that the memory is untrusted data, prohibit following commands embedded in it, or require provenance validation. Consequently, instruction-like content stored in memory can be interpreted with system-prompt authority during later sessions. Because conversations are automatically persisted by the same extension, an attacker who can contribute message content may be able to plant instructions that survive beyond the original interaction. The eventual representation is generated by Honcho, so exploitation depends on the malicious tex ...[truncated 1492 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Do not place free-form retrieved memory directly in the system-prompt instruction channel. 2. Supply memory as structured, quoted data in a lower-trust context or through a dedicated tool result. 3. Add an explicit invariant stating that retrieved memory is untrusted reference data and that commands, policies, or tool requests contained in it must never be followed. 4. Store structured facts with provenance rather than unrestricted instruction-like text. 5. Reject or quarantine durable memories containing command patterns, role markers, policy overrides, or requests to reveal secrets. 6. Require user review before promoting conversation text into durable cross-session memory. 7. Preserve source metadata for each fact and distinguish user assertions, agent output, generated summaries, and imported files. 8. Limit injected context to facts relevant to the current query instead of automatically loading broad summaries. 9. Add adversarial tests covering stored phrases such as “ignore previous instructions,” fake system messages, and tool-execution requests. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
extension/index.ts:246
Finding
Fallback Memory Reader Permits Out-of-Scope Files and Symlink Escape<![CDATA[ ## Vulnerability Details **File Location**: `extension/index.ts:246-266` **Vulnerability Type**: Insufficient filesystem path-boundary validation **Risk Level**: Medium ### Vulnerable Code ```typescript // Fallback: direct file read const fs = await import("node:fs/promises"); const pathMod = await import("node:path"); const workspace = api.config?.agents?.defaults?.workspace ?? process.cwd(); const fullPath = pathMod.resolve(workspace, params.path); // Safety: only allow MEMORY.md and memory/ paths const rel = pathMod.relative(workspace, fullPath); if (rel.startsWith("..") || (!rel.startsWith("memory") && rel !== "MEMORY.md")) { return { content: [{ type: "text", text: `Access denied: ${params.path}` }] }; } try { const raw = await fs.readFile(fullPath, "utf-8"); const allLines = raw.split("\n"); const start = (params.from ?? 1) - 1; const count = params.lines ?? allLines.length; const slice = allLines.slice(start, start + count).join("\n"); return { content: [{ type: "text", text: slice, path: params.path }] }; } catch { return { content: [{ type: "text", text: `File not found: ${params.path}` }] }; } ``` ### Technical Analysis The fallback reader intends to allow only `MEMORY.md` and files under the `memory/` directory, but it checks `rel.startsWith("memory")`. This prefix test also accepts unrelated workspace entries such as `memory-secrets.txt`, `memory-backup/`, and any other name beginning with the characters `memory`. The validation is lexical and occurs before filesystem resolution. `path.resolve()` and `path.relative()` normalize path segments but do not resolve symbolic links. A symlink located under the allowed `memory/` directory can therefore point to a file outside the workspace, while the lexical relative path still appears permitted. `fs.readFile()` subsequently follows that symlink. This code is used only when the built-in memory-get helper is unavailable. The vulnerable fallback nevertheless breaks the docum ...[truncated 1312 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enforce component-aware path checks: ```typescript const allowed = rel === "MEMORY.md" || rel.startsWith(`memory${pathMod.sep}`); if (!allowed || pathMod.isAbsolute(rel) || rel === ".." || rel.startsWith(`..${pathMod.sep}`)) { return accessDenied(); } ``` 2. Resolve the real paths of the workspace, memory directory, and requested target with `fs.realpath()`. 3. Verify that the target's real path is exactly the allowed file or remains beneath the real memory directory. 4. Reject symbolic links with `lstat()` when symlink support is unnecessary. 5. Require regular files and optionally enforce the documented `.md` extension. 6. Normalize and validate the configured workspace itself before using it as a security boundary. 7. Apply reasonable file-size and line-count limits to prevent excessive memory consumption. 8. Add tests for `memory-secrets.txt`, `memory-backup/file.md`, `../` traversal, absolute paths, platform-specific separators, and symlinks pointing outside the workspace. ]]>
Vulnerability Patterns
  • 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
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
Findings (22)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
This second description/behavior mismatch similarly indicates that the skill's stated purpose understates remote persistence, cross-session memory use, and active retrieval tooling. When a skill masks materially different behavior behind an installation-oriented description, it increases the risk of unintended data sharing and unauthorized memory influence over future agent responses.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding
This second description/behavior mismatch similarly indicates that the skill's stated purpose understates remote persistence, cross-session memory use, and active retrieval tooling. When a skill masks materially different behavior behind an installation-oriented description, it increases the risk of unintended data sharing and unauthorized memory influence over future agent responses.

Credential Access

High
Category
Privilege Escalation
Content
```bash
git clone https://github.com/plastic-labs/honcho
cd honcho
cp .env.template .env
cp docker-compose.yml.example docker-compose.yml
docker compose up -d
```
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Memory Manipulation

High
Category
Memory Poisoning
Content
- `BOOTSTRAP.md`
- `AGENT.md` (if this workspace uses it)

Preserve custom content; only replace memory-specific sections.

### Required policy text to add
Confidence
91% confidence
Finding
The skill instructs editing AGENTS.md, SOUL.md, BOOTSTRAP.md, and related control documents to replace memory-specific sections with new policy text. Those files govern agent behavior, so modifying them can permanently alter how the agent reasons about memory sources, trust, and persistence across sessions, creating a durable prompt-manipulation channel if done incorrectly or without review.

Intent-Code Divergence

High
Confidence
99% confidence
Finding
The honcho_session tool description says it retrieves history from the current session only, but the implementation calls honcho.session(params.sessionKey ?? "default"), allowing arbitrary session selection if a sessionKey is supplied. This mismatch can expose other sessions’ conversation history to an agent or user who relies on the documented restriction, creating an access-control and privacy boundary failure.

Intent-Code Divergence

High
Confidence
98% confidence
Finding
The tool claims it is restricted to the current session, but the implementation uses an arbitrary sessionKey from params when fetching Honcho session data. This creates an authorization/scope-bypass condition where a caller that can invoke the tool may retrieve history from other sessions, potentially exposing unrelated conversations and sensitive data.

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
95% confidence
Finding
The lockfile pins transitive dependency form-data to version 4.0.5, which is flagged with a high-severity CRLF injection advisory. If any code in this skill or its dependencies constructs multipart requests using attacker-controlled field names or filenames, an attacker could inject additional multipart headers or alter request structure, potentially enabling request smuggling-like behavior toward upstream services. In this skill’s context, the package set includes HTTP/form libraries through @honcho-ai/core, so the vulnerable package is plausibly reachable even though exploitation depends on unsafe input flow.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill explicitly depends on sensitive environment variables such as HONCHO_API_KEY, HONCHO_BASE_URL, HONCHO_WORKSPACE_ID, and WORKSPACE_ROOT, but it does not declare any tool scope or permission boundaries for environment access. That creates an avoidable trust gap: an agent following this skill may read and use secrets or host-specific configuration without clear least-privilege constraints or user approval semantics.

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The code automatically persists conversation messages to the Honcho cloud in the agent_end hook, while the manifest only describes installation, migration, and instruction updates. Hidden or under-disclosed remote persistence of conversation content is dangerous because it sends potentially sensitive user data off-box without clear expectation, informed consent, or scoped disclosure.

Missing User Warnings

Medium
Confidence
97% confidence
Finding
Conversation data is transmitted to a third-party cloud service automatically at the end of successful agent runs, with no explicit user-facing warning at the point of collection or persistence. In a memory-management skill, this context makes the issue more dangerous because users may assume local workspace memory behavior, while the code silently performs cross-session cloud storage of potentially sensitive prompts and responses.

Description-Behavior Mismatch

Medium
Confidence
96% confidence
Finding
The skill manifest describes setup and migration behavior, but the code also registers a broad suite of interactive Honcho memory query and analysis tools. This expands the skill’s operational scope beyond what a user or reviewer would reasonably expect, increasing the chance of unauthorized access to retained user data and making consent and review less meaningful.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The plugin automatically persists conversation messages to a cloud service at agent_end, but this file contains no user-facing notice, consent flow, or opt-in/opt-out control around that transmission. In a memory plugin, silent cloud export of user/assistant exchanges increases privacy risk because sensitive prompts, secrets, and personal data may be retained externally without informed user awareness.

Description-Behavior Mismatch

Medium
Confidence
88% confidence
Finding
The manifest describes a setup skill focused on installing/enabling Honcho memory, migrating legacy file memory, and updating instructions for retrieval behavior. In addition to retrieval-oriented tools, this plugin registers honcho_recall and honcho_analyze, which perform question-answering and synthesized analysis against stored user memory via chat calls, expanding the behavior beyond simple multiplexed retrieval/fallback.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
The manifest frames this as a setup/install-and-enable skill for memory mux behavior, legacy migration, and instruction updates. Registering a CLI with ask/search commands creates an operator-facing runtime interface for interrogating user memory, which is a separate capability not obviously required to install or enable the integration.

Missing User Warnings

Low
Confidence
88% confidence
Finding
The plugin reads the HONCHO_API_KEY environment variable to authenticate with an external service. While environment-variable access is expected for service integration, this file provides no user-facing notice that credentials are being consumed for remote memory synchronization.

Missing User Warnings

Low
Confidence
81% confidence
Finding
The honcho_context tool explicitly retrieves everything Honcho knows about the user across all sessions, which is privacy-relevant behavior. The code provides a tool description for the model, but no user-facing warning, confirmation, or disclosure to the end user about accessing aggregated long-term memory.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"clawhub-publish": "clawhub publish --slug honcho-memory-mux --name 'Honcho Memory Multiplexer'"
    },
    "dependencies": {
        "@honcho-ai/sdk": "^1.0.0",
        "@sinclair/typebox": "^0.32.0"
    },
    "peerDependencies": {
Confidence
90% confidence
Finding
Using a caret range for `@honcho-ai/sdk` permits automatic uptake of future minor and patch releases, which can introduce supply-chain risk or unexpected behavior changes without review. While common in development, this reduces build reproducibility and can matter for an extension that brokers memory and cloud interactions.

Unpinned Dependencies

Low
Category
Supply Chain
Content
},
    "dependencies": {
        "@honcho-ai/sdk": "^1.0.0",
        "@sinclair/typebox": "^0.32.0"
    },
    "peerDependencies": {
        "openclaw": "*"
Confidence
88% confidence
Finding
The caret range for `@sinclair/typebox` allows non-exact dependency resolution, which can cause non-reproducible installs and accidental adoption of compromised or breaking releases. This is a low-severity supply-chain hygiene issue rather than direct evidence of exploitation.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"@sinclair/typebox": "^0.32.0"
    },
    "peerDependencies": {
        "openclaw": "*"
    },
    "devDependencies": {
        "@types/node": "^24.0.0",
Confidence
98% confidence
Finding
The peer dependency on `openclaw` is completely unpinned using `*`, allowing installation with any version, including vulnerable or incompatible releases. In a security-sensitive extension ecosystem, this weakens supply-chain control and makes it impossible to reason about exposure to known OpenClaw advisories.

Unverifiable Dependency: openclaw has 16 known advisory(ies) (CVE-2026-53846 (OpenClaw: Workspace .env npm_execpath could influence bundled runtime dependency); CVE-2026-32064 (OpenClaw's andbox browser noVNC observer lacked VNC authentication); CVE-2026-32006 (OpenClaw has a BlueBubbles group allowlist mismatch via DM pairing-store fallbac) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
99% confidence
Finding
The manifest declares `openclaw` without a version constraint even though the package has multiple known advisories, so consumers may install an affected release without warning. Because this extension integrates directly with the OpenClaw ecosystem, the lack of version bounds materially increases exposure to known platform vulnerabilities.

Unpinned Dependencies

Low
Category
Supply Chain
Content
"openclaw": "*"
    },
    "devDependencies": {
        "@types/node": "^24.0.0",
        "typescript": "^5.9.0"
    }
}
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": "^24.0.0",
        "typescript": "^5.9.0"
    }
}
Confidence
40% confidence
Finding
Dependencies lack version pinning, allowing potential malicious package updates. Consider pinning versions.

Static analysis

Detected: suspicious.exposed_secret_literal

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
extension/dist/index.js:18