Back to skill

Security audit

Engram Memory

Security checks for vulnerabilities and agentic risk

Overview

Engram is a coherent local memory skill, but it enables automatic long-term capture and recall of conversation data and deploys exposed local services in ways users should review carefully before installing.

Review this skill before installing. It is designed to remember across sessions, so avoid enabling autoCapture for sensitive work unless you are comfortable storing conversation-derived facts locally. Bind Qdrant to 127.0.0.1 or add authentication before running the Docker stack, inspect and delete stored memories regularly, and treat recalled memories as untrusted context rather than instructions.

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

T02 · Agent Memory Poisoning

Error
Location
src/index.ts:396
Finding

Persistent Memory Poisoning Through Automatic Capture and Prompt Reinjection

Content
View full analysis
= { preference: /\b(prefer|like|always|never|want|love|hate|enjoy|favor|rather)\b/i, decision: /\b(decided|chosen|selected|will use|going with|switched to|moved to|picking)\b/i, fact: /\b(completed|version|status|count|running|deployed|migrated|installed|updated|is at|currently)\b/i, entity: /\b(company|team|person|project|service|app|platform|organization)\b/i, }; ``` ```ts private extractFacts(userMessage: string, agentResponse: string): string[] { const facts: string[] = []; const combined = `${userMessage}\n${agentResponse}`; const sentences = combined .split(/[.!?\n]+/) .map((s) => s.trim()) .filter((s) => s.length > 20); for (const sentence of sentences) { if (isNoise(sentence)) continue; if (sentence.endsWith("?")) continue; if (containsCredential(sentence)) continue; for (const pattern of Object.values(CATEGORY_PATTERNS)) { if (pattern.test(sentence)) { facts.push(scrubCredentials(sentence)); break; } } } return facts.slice(0, 3); } ``` ```ts const memoryBlock = relevant .map((m) => { const pct = Math.round((m.score || 0) * 100); return ` - [${m.category}] (${pct}% relevant) ${m.text}`; }) .join("\n"); const injection = ` Relevant memories from past sessions (use silently to inform ...[truncated 2614 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
docker-compose.yml:5
Finding

Unauthenticated Qdrant Memory Database Exposed on All Host Interfaces

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/recall/multi_head_hasher.py:353
Finding

Arbitrary Code Execution Through Automatic Pickle Deserialization

Content
View full analysis
"EngramMultiHeadHasher": """ Load a saved hasher from disk. The projection matrices are restored exactly, so hash signatures will match the original indexing. """ with open(path, "rb") as f: state = pickle.load(f) ``` The file is loaded automatically during engine warmup: ```py hash_path = os.path.join( self.config.data_dir, "hash_index.pkl" ) if os.path.exists(hash_path): try: self.hasher = EngramMultiHeadHasher.load(hash_path) logger.info( f"Restored hash index: {self.hasher.size} docs" ) except Exception as e: logger.warning( f"Failed to load hash index, starting fresh: {e}" ) ``` The default data directory is: ```py data_dir: str = ".engram" ``` ### Technical Analysis Python pickle is an executable serialization format. A crafted pickle can invoke attacker-selected callables during `pickle.load()`, before the returned object is validated. The recall engine automatically loads `hash_index.pkl` whenever it warms up and the file exists. No cryptographic integrity check, ownership verification, safe schema parser, or restrictive file-permission check is performed before deserialization. Catching an exception after `pickle.load()` does not prevent code that executed during deserialization. The attack requires an attacker to gain write access to the `.engram` directory or replace the file through another compromised process. Once that precondition is met, the unsafe loader converts file-write capability into execution under the agent process identity. ### Attack Path 1. An attacker gains write access to the plugin's `.engram` directory, a shar ...[truncated 1076 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned Python Dependencies and Mutable Container Image Executed During Setup

Content
View full analysis
=1.7.0 requests>=2.28.0 numpy>=1.21.0 click>=8.0.0 pyyaml>=6.0 httpx>=0.24.0 ``` The setup script installs whichever versions currently satisfy those ranges: ```py logger.info("Installing Python requirements...") subprocess.run([ str(pip_path), "install", "-r", str(self.requirements_file) ], check=True) ``` A separate setup path runs a mutable container tag: ```py subprocess.run([ "docker", "run", "-d", "--name", "engram-qdrant", "-p", "6333:6333", "-p", "6334:6334", "qdrant/qdrant:latest" ], check=True) ``` ### Technical Analysis Every Python dependency uses only a minimum-version constraint. A setup performed later can therefore install versions that were not present during review. Python package installation can execute build backends and other package-controlled code. The Qdrant fallback deployment uses `qdrant/qdrant:latest`, a mutable tag whose contents can change without a repository modification. The resulting runtime is therefore not reproducible and may differ from the audited version used in the Compose file. The audit did not identify a currently malicious dependency. The vulnerability is the uncontrolled trust placed in future package and image contents. ### Attack Path 1. A dependency account, package release, registry response, or mutable image tag is compromised or publishes a malicious future version. 2. A user runs `fastembed_setup.py` or another setup path that installs `requirements.txt`. 3. Pip selects the new version because the open-ended constraint permits it. 4. Alternatively, Docker resolves `qdrant/qdrant:latest` to newly changed image content. 5. The selected package or image executes with the installer or Docker dae ...[truncated 481 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
context/templates/web_app.yaml:128
Finding

Web Application Template Recommends Storing Bearer Tokens in localStorage

Content
View full analysis
{ const response = await fetch('/api/auth/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(credentials) }); const { token, user } = await response.json(); localStorage.setItem('token', token); return { token, user }; }; // Frontend: Authenticated requests const apiCall = async (url, options = {}) => { const token = localStorage.getItem('token'); return fetch(url, { ...options, headers: { ...options.headers, 'Authorization': `Bearer ${token}` } }); }; ``` ### Technical Analysis `localStorage` is readable by any JavaScript executing in the application's origin. If the application later develops an XSS vulnerability or loads a compromised same-origin script, that script can retrieve the bearer token. Because a bearer token normally authorizes requests solely based on possession, theft can allow an attacker to impersonate the victim until the token expires or is revoked. The YAML file is an inert documentation/template file and does not itself transmit real credentials. The risk arises when generated applications copy the recommended pattern. ### Attack Path 1. A developer adopts the template's authentication implementation. 2. A user logs in, and the application stores the JWT in `localStorage`. 3. An attacker exploits an XSS flaw or compromises a script executing in the same origin. 4. The malicious script calls `localStorage.getItem('token')`. 5. The attacker obtains the bearer token and uses it against the application's authenticated API. 6. Access continues until expiration, revocation, or another server-side restriction blocks the token. ### Impact Asse ...[truncated 338 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (161)

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Project/context search and question-answering over local data are meaningfully different from user-memory storage and recall. In practice, this can expand data exposure from conversational memory to arbitrary project files, which increases sensitivity and should be separately disclosed and permissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

Project/context search and question-answering over local data are meaningfully different from user-memory storage and recall. In practice, this can expand data exposure from conversational memory to arbitrary project files, which increases sensitivity and should be separately disclosed and permissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Project/context search and question-answering over local data are meaningfully different from user-memory storage and recall. In practice, this can expand data exposure from conversational memory to arbitrary project files, which increases sensitivity and should be separately disclosed and permissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

Project/context search and question-answering over local data are meaningfully different from user-memory storage and recall. In practice, this can expand data exposure from conversational memory to arbitrary project files, which increases sensitivity and should be separately disclosed and permissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding

Project/context search and question-answering over local data are meaningfully different from user-memory storage and recall. In practice, this can expand data exposure from conversational memory to arbitrary project files, which increases sensitivity and should be separately disclosed and permissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

Project/context search and question-answering over local data are meaningfully different from user-memory storage and recall. In practice, this can expand data exposure from conversational memory to arbitrary project files, which increases sensitivity and should be separately disclosed and permissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

Project/context search and question-answering over local data are meaningfully different from user-memory storage and recall. In practice, this can expand data exposure from conversational memory to arbitrary project files, which increases sensitivity and should be separately disclosed and permissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
92% confidence
Finding

Project/context search and question-answering over local data are meaningfully different from user-memory storage and recall. In practice, this can expand data exposure from conversational memory to arbitrary project files, which increases sensitivity and should be separately disclosed and permissioned.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
89% confidence
Finding

Project/context search and question-answering over local data are meaningfully different from user-memory storage and recall. In practice, this can expand data exposure from conversational memory to arbitrary project files, which increases sensitivity and should be separately disclosed and permissioned.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · context/cli/context_manager.py (reported line 298)May include surrounding context.

python
"apis.md": header + """# API Endpoints

## Authentication
- POST /auth/token - Get access token
- POST /auth/refresh - Refresh token
- GET /auth/me - Current user info

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 · context/cli/context_manager.py (reported line 307)May include surrounding context.

python
- POST /api/v1/items - Create item
- GET /api/v1/items/{id} - Get item
- PUT /api/v1/items/{id} - Update item
- DELETE /api/v1/items/{id} - Delete item

## Response Format
```json

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% 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 · context/templates/web_app.yaml (reported line 183)May include surrounding context.

yaml
POST   /api/v1/users          # Create new user  
    GET    /api/v1/users/:id      # Get specific user
    PUT    /api/v1/users/:id      # Update user
    DELETE /api/v1/users/:id      # Delete user
    ```

    ### Error Response Format

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% 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 · context/templates/web_app.yaml (reported line 469)May include surrounding context.

yaml
POST   /api/v1/users          # Create new user  
    GET    /api/v1/users/:id      # Get specific user
    PUT    /api/v1/users/:id      # Update user
    DELETE /api/v1/users/:id      # Delete user
    ```

    ### Error Response Format

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · context/templates/web_app.yaml (reported line 566)May include surrounding context.

yaml
3. **Environment configuration**
       ```bash
       # Copy environment templates
       cp .env.example .env
       
       # Configure database connection, JWT secret, etc.
       ```

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · context/templates/web_app.yaml (reported line 787)May include surrounding context.

yaml
3. **Environment configuration**
       ```bash
       # Copy environment templates
       cp .env.example .env
       
       # Configure database connection, JWT secret, etc.
       ```

Instruction Override

High
Category
Prompt Injection
Confidence
70% confidence
Finding

This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Content

Scanner excerpt · docs/OPENCLAW_INTEGRATION.md (reported line 71)May include surrounding context.

memory_store "Testing Engram integration" --category fact

memory_search "testing"

5. Enable debug mode to see hook activity:

Set "debug": true in config, then:

openclaw gateway logs --follow | grep engram

text

os.system() or os exec-family call

High
Category
Dangerous Code Execution
Confidence
85% confidence
Finding

os.system() and os exec-family calls run shell commands with the process's full privileges, enabling arbitrary command execution.

Content

Scanner excerpt · scripts/mcp_server.py (reported line 4)May include surrounding context.

python
#!/usr/bin/env python3
"""Redirect — MCP server has moved to mcp/server.py"""
import os, sys
sys.exit(os.execvp(sys.executable, [sys.executable, os.path.join(os.path.dirname(__file__), "..", "mcp", "server.py")] + sys.argv[1:]))

YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]

High
Category
YARA Match
Confidence
75% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · scripts/setup-context.sh (reported line 84)May include surrounding context.

sh
$COMMANDS_DIR/engram-ask" << 'EOF'
#!/bin/bash
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
PERFECT_RECALL_ROOT="$(dirname "$SCRIPT_DIR")"
python3 "$PERFECT_RECALL_ROOT/context/tools/context_assistant.py" "$@"
EOF

chmod +x "$COMMANDS_DIR"/*

# Update PATH recommendation
echo -e "${YELLOW}📝 Adding to PATH...${NC}"
if ! echo "$PATH" | grep -q "$COMMANDS_DIR"; then
    echo "export PATH=\"$COMMANDS_DIR:\$PATH\"" >> "$HOME/.bashrc"
    echo -e "${GREEN}✅ Added Engram commands to PATH${NC}"
    echo -e "${YELLOW}   Run: source ~/.bashrc  (or restart terminal)${NC}"
fi

# Check if Engram memory system is running
echo -e "${YELLOW}🔍 Checking Engram services...${NC}"
if curl -s http://localhost:6333/health > /dev/null 2>&1; then
    echo -e "${GREEN}✅ Qdrant vector store is running${NC}"
    QDRANT_RUNNING=true
else
    echo -e "${YELLOW}⚠️  Qdrant vector store not running${NC}"
    echo "   Context system will work with reduced functionality"
    echo

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
95% 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 · scripts/setup.sh (reported line 254)May include surrounding context.

sh
fi

if [ "$VENV_OK" = false ]; then
    rm -rf "$SKILL_DIR/.venv" 2>/dev/null
    echo -e "${YELLOW}venv unavailable — installing with pip3${NC}"
    pip3 install --user -q -r "$SKILL_DIR/requirements.txt" 2>&1 | tail -1
    echo -e "${GREEN}Python dependencies installed (user)${NC}"

Missing User Warnings

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

afterAgentResponse automatically extracts and stores conversation content in a remote vector database without any consent, notice, or confirmation path visible in this file. This creates covert retention of user data and can capture personal, regulated, or business-sensitive information even when explicit credentials are filtered.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The README documents automatic recall and automatic capture of conversation-derived memories, but it does not prominently warn users that sensitive prompts, secrets, personal data, or regulated information may be persisted to local storage automatically. In a memory tool for AI agents, silent persistence of conversational content increases the risk of unintended retention, later disclosure through search/recall, and privacy or compliance issues even if storage is local-only.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill documents shell, network, file read/write, and environment-related capabilities but does not declare an explicit permission or allowed-tools scope. That increases the chance an agent or operator grants broader access than intended, especially because the skill includes setup scripts, Docker usage, config modification, and local HTTP interactions. In this context, the lack of scoping is meaningful because the skill is not read-only documentation; it instructs execution of privileged local operations.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill encourages persistent retention of user preferences, facts, and past decisions across sessions without clear minimization boundaries. In an agent setting, that creates a predictable risk of over-collection and long-lived storage of sensitive or unnecessary data, especially when semantic recall can resurface it in later contexts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Enabling automatic capture of user/context data without a strong, explicit privacy warning creates a real privacy and compliance risk. Users may not realize that conversation content or project details are being persisted and semantically indexed across sessions, which can include sensitive personal, business, or credential-adjacent information.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

Automatic saving of conversational context is a concrete data-retention risk because it captures free-form natural language that often contains sensitive details users did not intend to persist. The danger is amplified here because the feature is framed as helpful automation, while the privacy boundaries and safeguards are underexplained.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.