Back to skill

Security audit

Memory Garden - Validated Community Memory

Security checks for vulnerabilities and agentic risk

Overview

This is a coherent memory skill, but it automatically runs a local daemon and injects stored or community knowledge into prompts in a way users should review before installing.

Review this before installing if you handle secrets or sensitive work in prompts. It will start a local background daemon, store memory under ~/.memory-garden, and by default add matching stored knowledge into model prompts. Keep sync and extraction disabled unless you intentionally want sharing or conversation harvesting, and treat community patterns as untrusted content.

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

T01 · Skill Instruction Hijacking

Error
Location
index.ts:125
Finding

Untrusted Retrieved Pattern Content Is Injected Directly into the Model Prompt

Content
View full analysis

Vulnerability Details

File Location: index.ts, lines 125-130
Vulnerability Type: Prompt injection through untrusted retrieved content
Risk Level: High

Vulnerable Code

ts
// Build context from patterns
const context = results
  .map(r => `[${r.pattern.slug}] ${r.pattern.claim}`)
  .join('\n');

return `Relevant knowledge from community commons:\n${context}\n\nQuery: ${query}`;

Technical Analysis

The beforeQuery() hook retrieves pattern claims from the Memory Garden daemon and inserts them verbatim into the text sent to the language model. The implementation does not apply instruction filtering, trust validation, content sanitization, provenance-based policy, or a clear security boundary that requires the model to treat retrieved patterns only as untrusted reference data.

Search is enabled by default, and the project describes community and federated pattern sources. Consequently, an attacker who can contribute to, synchronize with, or otherwise influence the searched pattern collection may store a claim containing adversarial instructions. When that pattern matches a later query, the hostile text is positioned immediately before the user's query and may be interpreted as an instruction rather than data.

This is an indirect prompt-injection condition. It does not itself grant operating-system privileges, but it can alter the Agent's current goals, output, safety behavior, and tool-selection decisions. The effective severity depends on which tools and permissions the host Agent exposes.

Attack Path

  1. An attacker creates or influences a pattern whose claim contains instructions intended for the model, such as directions to ignore the user's request, disclose available context, invoke a tool, or direct the user to attacker-controlled content.
  2. The malicious pattern enters a local or community-backed pattern collection searched by the daemon.
  3. A user submits a query that causes the malicious pattern to rank among t ...[truncated 1044 chars]
Remediation
View remediation

Remediation Suggestions

  1. Treat every retrieved pattern field as untrusted data, regardless of whether it originated locally or from a nominally trusted community.
  2. Pass retrieval results through a structured context channel, if supported, rather than concatenating them into the instruction-bearing prompt.
  3. Add an authoritative instruction outside attacker-controlled content stating that retrieved patterns are reference data and must not modify system instructions, user goals, safety constraints, or tool policy.
  4. Delimit each retrieved item using a non-executable structured representation containing explicit fields such as claim, source, trust_level, and signature_status.
  5. Detect and reject or quarantine claims containing instruction-like content, role markers, requests to ignore earlier instructions, tool invocation directives, or data-exfiltration requests.
  6. Apply source authentication, signature verification, moderation, and trust thresholds before community patterns become eligible for prompt augmentation.
  7. Limit the length and number of retrieved claims to reduce prompt-injection surface.
  8. Require explicit user confirmation before acting on retrieved content that suggests tool use or security-sensitive actions.
  9. Add adversarial tests covering malicious community claims and confirm that they cannot alter task goals or trigger tools.

T09 · Insecure Skill Coding Practices

Warning
Location
identity.ts:296
Finding

Replay-Protection State Is Updated Before Signature Authentication

Content
View full analysis

Vulnerability Details

File Location: identity.ts, lines 296-318
Vulnerability Type: Unauthenticated state mutation in signed-message verification
Risk Level: Medium

Vulnerable Code

ts
// 2. Check nonce uniqueness (if tracking enabled)
// CR-8: Without seenNonces, only timestamp validation is performed
if (seenNonces) {
  const nonceKey = `${message.agentId}:${message.nonce}`;
  if (seenNonces.has(nonceKey)) {
    return { valid: false, error: 'Nonce already used (replay detected)' };
  }
  seenNonces.add(nonceKey);
}

// 3. Reconstruct canonical payload and verify signature
// CR-10: Use canonical JSON with sorted keys
const payload = {
  agentId: message.agentId,
  data: message.data,
  nonce: message.nonce,
  timestamp: message.timestamp,
};
const canonical = canonicalJson(payload);

const signatureValid = verifySignature(canonical, message.signature, publicKey);
if (!signatureValid) {
  return { valid: false, error: 'Invalid signature' };
}

Technical Analysis

verifyMessage() adds the message's nonce to the caller-provided seenNonces set before validating the Ed25519 signature. Both agentId and nonce are attacker-controlled until signature verification succeeds.

As a result, a message with an invalid signature still permanently mutates replay-protection state. Repeated forged messages with unique nonces can grow an unbounded set. In addition, an attacker who learns or predicts a nonce used by a legitimate message may submit an invalid message containing the same agentId and nonce first. The forged message fails signature verification, but the nonce remains reserved, causing the subsequent authentic message to be rejected as a replay.

The issue affects integrations that call verifyMessage() on adversarial input and provide a persistent seenNonces set. The reviewed repository does not show a concrete network handler invoking this function, so practical exposure depends on its downstream use.

Attack Path

...[truncated 1418 chars]

Remediation
View remediation

Remediation Suggestions

  1. Validate the timestamp and reconstruct the canonical payload first.
  2. Verify the Ed25519 signature before reading or modifying replay-protection state.
  3. After successful authentication, atomically check and insert the authenticated nonce.
  4. Do not retain any nonce from a message whose signature is invalid.
  5. Use an expiring replay cache whose entries are removed after maxAgeMs.
  6. Enforce a maximum cache size and per-agent rate limits to prevent memory exhaustion.
  7. Validate nonce format and length before cryptographic processing.
  8. Where verification is concurrent, use an atomic check-and-set operation so two simultaneous copies of the same authenticated message cannot both pass.
  9. Add tests confirming that invalid signatures never mutate seenNonces, replayed valid messages are rejected, and expired entries are removed.

A safe ordering is:

ts
// Validate timestamp and message fields first.

const payload = {
  agentId: message.agentId,
  data: message.data,
  nonce: message.nonce,
  timestamp: message.timestamp,
};

const canonical = canonicalJson(payload);
if (!verifySignature(canonical, message.signature, publicKey)) {
  return { valid: false, error: 'Invalid signature' };
}

// Only authenticated messages may affect replay state.
if (seenNonces) {
  const nonceKey = `${message.agentId}:${message.nonce}`;
  if (seenNonces.has(nonceKey)) {
    return { valid: false, error: 'Nonce already used (replay detected)' };
  }
  seenNonces.add(nonceKey);
}
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (29)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Automatic pre-query augmentation, post-response extraction, daemon-mediated processing, and submission of validation events can expose full conversation contents to a local or configured backend service. In context, a knowledge/memory skill makes this more dangerous because users may assume 'local-first' equals harmless, while the actual behavior can still persist sensitive data, reshape prompts, and potentially forward information if configuration changes enable sync or remote daemon URLs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Automatic pre-query augmentation, post-response extraction, daemon-mediated processing, and submission of validation events can expose full conversation contents to a local or configured backend service. In context, a knowledge/memory skill makes this more dangerous because users may assume 'local-first' equals harmless, while the actual behavior can still persist sensitive data, reshape prompts, and potentially forward information if configuration changes enable sync or remote daemon URLs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Automatic pre-query augmentation, post-response extraction, daemon-mediated processing, and submission of validation events can expose full conversation contents to a local or configured backend service. In context, a knowledge/memory skill makes this more dangerous because users may assume 'local-first' equals harmless, while the actual behavior can still persist sensitive data, reshape prompts, and potentially forward information if configuration changes enable sync or remote daemon URLs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Automatic pre-query augmentation, post-response extraction, daemon-mediated processing, and submission of validation events can expose full conversation contents to a local or configured backend service. In context, a knowledge/memory skill makes this more dangerous because users may assume 'local-first' equals harmless, while the actual behavior can still persist sensitive data, reshape prompts, and potentially forward information if configuration changes enable sync or remote daemon URLs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Automatic pre-query augmentation, post-response extraction, daemon-mediated processing, and submission of validation events can expose full conversation contents to a local or configured backend service. In context, a knowledge/memory skill makes this more dangerous because users may assume 'local-first' equals harmless, while the actual behavior can still persist sensitive data, reshape prompts, and potentially forward information if configuration changes enable sync or remote daemon URLs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Automatic pre-query augmentation, post-response extraction, daemon-mediated processing, and submission of validation events can expose full conversation contents to a local or configured backend service. In context, a knowledge/memory skill makes this more dangerous because users may assume 'local-first' equals harmless, while the actual behavior can still persist sensitive data, reshape prompts, and potentially forward information if configuration changes enable sync or remote daemon URLs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Automatic pre-query augmentation, post-response extraction, daemon-mediated processing, and submission of validation events can expose full conversation contents to a local or configured backend service. In context, a knowledge/memory skill makes this more dangerous because users may assume 'local-first' equals harmless, while the actual behavior can still persist sensitive data, reshape prompts, and potentially forward information if configuration changes enable sync or remote daemon URLs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Automatic pre-query augmentation, post-response extraction, daemon-mediated processing, and submission of validation events can expose full conversation contents to a local or configured backend service. In context, a knowledge/memory skill makes this more dangerous because users may assume 'local-first' equals harmless, while the actual behavior can still persist sensitive data, reshape prompts, and potentially forward information if configuration changes enable sync or remote daemon URLs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding

Automatic pre-query augmentation, post-response extraction, daemon-mediated processing, and submission of validation events can expose full conversation contents to a local or configured backend service. In context, a knowledge/memory skill makes this more dangerous because users may assume 'local-first' equals harmless, while the actual behavior can still persist sensitive data, reshape prompts, and potentially forward information if configuration changes enable sync or remote daemon URLs.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

Automatic pre-query augmentation, post-response extraction, daemon-mediated processing, and submission of validation events can expose full conversation contents to a local or configured backend service. In context, a knowledge/memory skill makes this more dangerous because users may assume 'local-first' equals harmless, while the actual behavior can still persist sensitive data, reshape prompts, and potentially forward information if configuration changes enable sync or remote daemon URLs.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill advertises executable behavior that includes environment access, local networking, and shell/process management, but it does not declare an explicit tool scope such as permissions or allowed-tools. That creates a transparency and least-privilege problem: users and hosting platforms cannot easily constrain what the skill may do, increasing the risk of unexpected command execution, filesystem access, or daemon control.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The code spawns a detached background daemon with stdio ignored, which can leave a persistent process running without clear user awareness. In an agent/skill context, undisclosed background execution materially expands operational risk because the process can continue listening on a local port, consuming resources, and persisting state after the triggering action appears complete.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill can terminate background processes via SIGTERM based on a stored PID and process-name verification, yet users are not clearly warned that invoking shutdown or startup recovery may kill an existing local process. Although the code includes safeguards, process termination is still a sensitive action in an agent setting because mistaken or unexpected termination can disrupt legitimate local workloads and cause data loss or availability issues.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · config.ts (reported line 65)May include surrounding context.

ts
function validateConfig(config) {
    const warnings = [];
    if (config.extraction.enabled && !config.extraction.confirmRequired) {
        warnings.push('Extraction enabled without confirmation - patterns may be extracted automatically');
    }
    if (config.sync.enabled && !config.extraction.enabled) {
        warnings.push('Sync enabled but extraction disabled - you can receive but not contribute patterns');

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · dist/config.js (reported line 51)May include surrounding context.

js
function validateConfig(config) {
    const warnings = [];
    if (config.extraction.enabled && !config.extraction.confirmRequired) {
        warnings.push('Extraction enabled without confirmation - patterns may be extracted automatically');
    }
    if (config.sync.enabled && !config.extraction.enabled) {
        warnings.push('Sync enabled but extraction disabled - you can receive but not contribute patterns');

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The code spawns a detached daemon process via spawn(...), which is a safety-relevant operation under the rule. While there are developer comments and error logs for failures, there is no user-facing disclosure before or at the time the daemon is started, and no visible prompt or warning in this file indicating that a background process will be launched.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

The code writes daemon.pid into the skill data directory using writeFileSync, which is a file-modifying operation covered by the missing-warning rule for code files. Although the behavior is commented for developers, there is no user-facing print, prompt, or warning in this file that a PID file will be created under the user's home data directory.

Content

No source excerpt is available for this finding.

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · dist/identity.js (reported line 94)May include surrounding context.

js
// Allow 0o600 (owner read/write) or 0o400 (owner read)
        if (mode !== 0o600 && mode !== 0o400) {
            console.warn(`[memory-garden] Identity file has permissions ${mode.toString(8)}, ` +
                `expected 0600. Consider running: chmod 600 ${IDENTITY_FILE}`);
        }
    }
    // CR-9: Try-catch around JSON.parse

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · identity.ts (reported line 114)May include surrounding context.

ts
// Allow 0o600 (owner read/write) or 0o400 (owner read)
        if (mode !== 0o600 && mode !== 0o400) {
            console.warn(`[memory-garden] Identity file has permissions ${mode.toString(8)}, ` +
                `expected 0600. Consider running: chmod 600 ${IDENTITY_FILE}`);
        }
    }
    // CR-9: Try-catch around JSON.parse

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill automatically rewrites prompts in beforeQuery() and harvests query/response content in afterResponse(), which goes beyond a simple local-first knowledge lookup and materially changes both data flow and model interaction. This is dangerous because users or hosts may not expect their prompts and model outputs to be programmatically transmitted to another service and used for extraction, creating privacy, consent, and prompt-integrity risks.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The call sites automatically transmit user query data to a daemon via callMcpTool() without any visible inline warning, consent gate, or sensitivity check. In this skill context, that is more dangerous because the feature is framed as local-first/community-ready, which may lower user suspicion even though prompts and possibly responses are being sent over HTTP to another process or endpoint.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

afterResponse() sends the full original query and full model response to extractPatterns(), which forwards them to the daemon without redaction or user confirmation. If conversations contain secrets, personal data, credentials, internal code, or regulated content, this creates a direct exfiltration channel and broad privacy exposure disproportionate to the stated skill purpose.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The beforeQuery hook automatically sends user queries to the daemon for search-based augmentation without a user-facing warning or consent step. Even if intended to improve answers, this silently transmits potentially sensitive user input to another service boundary, which is especially risky because the augmentation is automatic and fail-open behavior may hide the data flow from users.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The skill sends both the user's query and the model's response to a daemon for pattern extraction, but there is no explicit consent, disclosure, or redaction at the call site. Because responses may contain sensitive prompts, personal data, secrets, or proprietary content, this creates a real privacy and data-handling risk even if the daemon is local-first.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
90% confidence
Finding

This code initializes a persistent data directory under the user's home directory and later stores daemon state in a PID file. Although the behavior is visible in code comments, there is no user-facing warning, prompt, or explanatory docstring/comment aimed at disclosing that the skill will create and manage files on disk.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.env_credential_access

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
daemon-manager.ts:162

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
daemon-manager.ts:18

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
dist/daemon-manager.js:52