Back to skill

Security audit

Jasper Recall

Security checks for vulnerabilities and agentic risk

Overview

This memory skill is coherent in purpose, but it has serious implementation and privacy-boundary problems that warrant Review before installation.

Install only after reviewing and fixing the shell execution paths, pinning dependencies, and tightening memory isolation. Do not expose the recall server beyond localhost, do not enable RECALL_ALLOW_PRIVATE on shared hosts, set publicOnly for untrusted agents, and rebuild or purge existing ChromaDB data after privacy-boundary fixes.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (7)

T09 · Insecure Skill Coding Practices

Error
Location
cli/server.js:20
Finding

Unauthenticated OS Command Injection in the HTTP Recall API

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
extensions/openclaw-plugin/index.ts:48
Finding

OS Command Injection in the OpenClaw Recall Plugin

Content
View full analysis
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/index-digests.py:64
Finding

Whole-File Classification Exposes Private Sections Through Shared Collections

Content
View full analysis
str: rel_lower = rel_path.lower() content_lower = content.lower() if any(x in rel_lower for x in ['moltbook/', 'learnings/', 'agent-insights/']): return 'learnings' if '[learning]' in content_lower or '[insight]' in content_lower: return 'learnings' if 'shared/' in rel_lower: return 'shared' if '[public]' in content_lower: return 'shared' return 'private' ``` The complete file is subsequently chunked and added to the selected collection: ```python # Chunk the content chunks = chunk_text(content) if not chunks: return False # Generate embeddings embeddings = model.encode(chunks).tolist() ids = [f"{rel_path}::{i}" for i in range(len(chunks))] metadatas = [ { "source": rel_path, "chunk_index": i, "file_hash": file_hash, "filename": filename, } for i in range(len(chunks)) ] collection.add( ids=ids, embeddings=embeddings, documents=chunks, metadatas=metadatas ) ``` ### Technical Analysis Collection selection is performed once for the entire file. The presence of a single `[public]`, `[learning]`, or `[insight]` marker classifies every chunk from that file as shared or as an agent learning. Daily notes are explicitly documented as potentially containing both public and private sections. Consequently, an untagged or `[private]` section in the same file as one public section is indexed into a collection accessible to sandboxed agents. ### Attack Path 1. A daily memory file contains a legitimate `[public]` section and one or more private sections. 2. `determine_collection` finds `[public]` anywhere in the file and returns `shared`. 3. `chunk_t ...[truncated 522 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
scripts/recall.py:108
Finding

Public-Only Recall Falls Back to an Unrestricted Legacy Collection

Content
View full analysis
Remediation
View remediation

T02 · Agent Memory Poisoning

Error
Location
scripts/write-learning.py:64
Finding

Sandboxed Agents Can Persist Unreviewed Content into Shared Agent Memory

Content
View full analysis
`- [${r.source || 'memory'}] ${r.content.slice(0, 500)}${r.content.length > 500 ? '...' : ''}`) .join('\n'); return { prependContext: `\nThe following memories may be relevant to this conversation:\n${memoryContext}\n`, }; ``` ### Technical Analysis The writer is explicitly designed for sandboxed agents, but it applies only length checks and category validation. It does not require approval, establish content trust, detect embedded instructions, or quarantine submissions before adding them to the shared Markdown file and `agent_learnings` collection. Retrieved content is formatted as raw agent-visible context. An untrusted agent can therefore store text that resembles system instructions, tool-use requests, or false operational facts for later retrieval. The current plugin has a correctness mismatch: `recall.py` emits `similarity`, while the plugin filters on `r.score`. This suppresses normal automatic recall in the reviewed version, but the poisoned content remains persistent and is still available through manual recall. Correcting that mismatch without adding tr ...[truncated 1056 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/sync-shared.py:51
Finding

Shared-Memory Synchronization Does Not Enforce the Privacy Scanner

Content
View full analysis
list: content = filepath.read_text() sections = [] for match in PUBLIC_SECTION_PATTERN.finditer(content): level = match.group(1) title = match.group(2).strip() body = match.group(3).strip() date = filepath.stem if re.match(r'\d{4}-\d{2}-\d{2}', filepath.stem) else "unknown" sections.append({ "date": date, "level": level, "title": title, "body": body, "source": filepath.name }) return sections ``` The extracted content is then written directly: ```python all_sections = [] for note in notes: sections = extract_public_sections(note) if sections: print(f" {note.name}: {len(sections)} [public] section(s)") all_sections.extend(sections) product_sections = [s for s in all_sections if categorize_section(s) == "product"] learning_sections = [s for s in all_sections if categorize_section(s) == "learning"] if product_sections: added = update_shared_file(PRODUCT_UPDATES, product_sections, args.dry_run) if learning_sections: added = update_shared_file(LEARNINGS, learning_sections, args.dry_run) ``` ### Technical Analysis Although the project provides `privacy-check.py` and documentation recommends running it, `sync-shared.py` does not import, invoke, or enforce the scanner. The `[public]` marker is treated as sufficient authorization to copy the title and body verbatim. This makes privacy protection dependent on a separate manual step that can be forgotten, bypassed by automation, or defeated by user error. ### Attack Path 1. A m ...[truncated 671 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
cli/jasper-recall.js:137
Finding

Setup Installs Unpinned Python Dependencies at Runtime

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (91)

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SKILL.md (reported line 424)May include surrounding context.

"Collection not found"

bash
rm -rf ~/.openclaw/chroma-db  # Clear and rebuild
index-digests

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
90% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · SKILL.md (reported line 424)May include surrounding context.

"Collection not found"

bash
rm -rf ~/.openclaw/chroma-db  # Clear and rebuild
index-digests

Rp1

Medium
Category
MCP Rug Pull
Confidence
93% confidence
Finding

The changelog recommends executing npx jasper-recall serve --port 3458 without pinning a package version. npx will resolve the latest available package at execution time, so users may run a newer or compromised release than the one documented, creating a supply-chain risk if the package is hijacked or a malicious update is published.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

The documented setup command uses npx jasper-recall setup without an explicit version. This exposes users to execution of whatever version npm resolves at that moment, which is especially risky for bootstrap/setup flows because they typically run with broad filesystem and configuration access.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding

The update example npx jasper-recall update is unpinned and therefore can fetch and execute an unintended package version. Because this command is specifically about updates, users may be conditioned to trust remote code execution paths, increasing the chance of supply-chain compromise if the package or dependency chain is tampered with.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The configuration example references npx jasper-recall config without pinning the package version. Even though this appears lower risk than setup, it still executes code fetched at runtime and can be abused through package compromise, typo-squatting, or malicious release publication.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

The README instructs users to execute npx jasper-recall setup without pinning a version. Because npx resolves the latest published package at execution time, a compromised maintainer account, dependency confusion event, or malicious future release could cause arbitrary code execution on the user's machine during installation.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The documented command npx jasper-recall doctor invokes code fetched by package name without a pinned version. Even though this is framed as a health check, it still executes package code locally and could be abused if the package or its distribution path is compromised.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

npx jasper-recall doctor --fix is more dangerous than a read-only check because it both fetches unpinned code and then performs environment modifications like creating venvs and installing packages. A malicious or tampered upstream release could leverage this trusted repair flow to run arbitrary commands and persist changes.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

npx jasper-recall doctor --dry-run still executes unpinned package code despite sounding non-invasive. Users may incorrectly assume dry-run is safe, but the initial package resolution and execution remain a supply-chain risk.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · README.md (reported line 214)May include surrounding context.

md
### Setup for Sandboxed Agents

1. Create shared directory: `mkdir -p ~/.openclaw/workspace/memory/shared`
2. Symlink to sandboxed workspace: `ln -s ~/.openclaw/workspace/memory/shared ~/.openclaw/workspace-sandbox/shared`
3. Use `--public-only` flag in sandboxed agent's recall queries

Rp1

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding

The README documents npx jasper-recall serve without version pinning, causing users to run the latest package code when starting a local API server. Because server startup often involves long-lived processes and access to local memory data, compromise of the package can expose sensitive information and permit persistent malicious behavior.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
91% confidence
Finding

npx jasper-recall serve --port 8080 has the same unpinned remote execution risk as other npx examples. In this context the impact is amplified because the process exposes an HTTP interface that may handle sensitive memory content, so a malicious release could both execute code and alter server behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The plugin's auto-recall feature injects retrieved memories from past conversations into every message context, but the README does not prominently warn about the privacy implications or obtain explicit user consent. In an agent-memory product, this can unintentionally surface sensitive historical content to prompts, tools, logs, or downstream models beyond what the user expects.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
92% confidence
Finding

The setup instructions again rely on npx jasper-recall setup without version pinning. This is a classic supply-chain footgun because installation/setup commands are high-trust operations that typically receive broad filesystem permissions and can modify agent configuration.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

The skill instructs users to run npx jasper-recall setup without pinning a specific package version. This allows whatever version is current on npm at execution time to be fetched and run, creating a supply-chain risk if a future release is malicious, compromised, or breaking. In a security-sensitive agent skill, executing unpinned remote code is dangerous because installation happens with user privileges and sets up persistent binaries and services.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
86% confidence
Finding

The skill explicitly promotes creation of session digests from prior conversations, which establishes persistent storage and retrieval of interaction history. While this is core functionality rather than malicious behavior, it increases privacy and data-retention risk because sensitive prompts, secrets, or personal data may be summarized and made searchable across sessions. In an agent-memory skill, this is contextually expected but still security-relevant.

Content

Scanner excerpt · SKILL.md (reported line 76)May include surrounding context.

index-digests # Index memory files into ChromaDB

text

**Create session digests:**
```bash
digest-sessions          # Process new sessions
digest-sessions --dry-run  # Preview what would be processed

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

npx jasper-recall moltbook-setup fetches and executes an unpinned package version from npm. Because this command configures wrappers for sandboxed agents, a malicious or unexpected package update could alter the isolation model or install backdoored scripts. The security context makes the risk higher because this command establishes trust boundaries for other agents.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
95% confidence
Finding

npx jasper-recall moltbook-verify is another unpinned execution path to code retrieved at runtime. Verification commands are especially sensitive because users may trust their output to confirm isolation or privacy guarantees, but an altered package could falsely report a secure state. This creates both code-execution and trust-manipulation risk.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The documentation claims sandboxed agents can only search shared memories via a wrapper that forces --public-only, but elsewhere it documents direct collection selection flags such as --collection private_memories and --all. If the sandboxed agent can invoke the underlying CLI directly instead of only the wrapper, the privacy boundary becomes policy-only rather than technically enforced. This mismatch can lead to private memory disclosure in multi-agent environments.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
94% confidence
Finding

The serve command is documented as npx jasper-recall serve [OPTIONS], again causing unpinned package execution. Since this starts a long-lived HTTP API over local memory data, a compromised future package version could expose data, weaken defaults, or open additional network-accessible behavior. The network-facing nature of this component increases impact.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · SKILL.md (reported line 419)May include surrounding context.

"No index found"

bash
index-digests  # Create the index first

"Collection not found"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The document plans and tracks implementation of bidirectional memory sharing, shared directories, symlinks, and scheduled sync between agents, but it does not prominently warn about the privacy and data-exposure risks of cross-agent memory propagation. In this context, agents may handle sensitive prompts, notes, or derived data, so normalizing shared-memory features without explicit guardrails increases the chance of unintended disclosure or privacy-boundary bypass.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The file is presented as a 'system health check', but when run with --fix it creates directories, creates a Python virtual environment, installs packages with pip, and runs an indexing script. That mismatch increases the chance a user or calling agent will treat it as read-only diagnostics and trigger state-changing operations without adequate consent or review.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · cli/jasper-recall.js (reported line 7)May include surrounding context.

js
* Local RAG system for AI agent memory
 * 
 * Usage:
 *   npx jasper-recall setup     # Install dependencies and create scripts
 *   npx jasper-recall recall    # Run a query (alias)
 *   npx jasper-recall index     # Index files (alias)
 *   npx jasper-recall digest    # Digest sessions (alias)

Static analysis

Detected: suspicious.dangerous_exec, suspicious.destructive_delete_command

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
cli/doctor.js:15

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
cli/jasper-recall.js:43

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
cli/server.js:33

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
extensions/jasper-recall/index.ts:58

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
extensions/openclaw-plugin/index.ts:58

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/index.js:28

Documentation contains a destructive delete command without an explicit confirmation gate.

Warn
Code
suspicious.destructive_delete_command
Location
SKILL.md:424