Back to skill

Security audit

Engram MCP Server

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent expert-memory MCP server, but its install path, remote pack loading, persistent memory, and local editing UI are too broad and under-controlled for automatic trust.

Install only after reviewing the source and pinning the version you run. Avoid the curl-to-shell installer path, be cautious with remote Engram packs, and do not store sensitive personal, health, credential, or business data in memory until category path validation, consent controls, and UI authentication are fixed. Do not leave the web UI running while browsing untrusted sites.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • 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
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (5)

T03 · Remote Payload Retrieval and Execution

Error
Location
SKILL.md:8
Finding

Unverified Remote Installer Is Executed Directly by a Shell

Content
View full analysis
Remediation
View remediation

T01 · Skill Instruction Hijacking

Error
Location
src/engram_server/server.py:301
Finding

Mutable Remote Engram Packs Are Loaded as Trusted Agent Instructions

Content
View full analysis
list[dict]: try: with urlopen(REGISTRY_URL, timeout=30) as response: payload = response.read().decode("utf-8") except (OSError, URLError, TimeoutError): return [] ``` ```python def install_engram_from_source(source: str, packs_dir: Path) -> dict[str, str | bool]: packs_dir = packs_dir.expanduser() packs_dir.mkdir(parents=True, exist_ok=True) target_name = _derive_target_name(source) target_dir = packs_dir / target_name subprocess.run( ["git", "clone", source, str(target_dir)], capture_output=True, text=True, check=True, ) return _finalize_installed_pack(target_dir) ``` Installation validation only checks for a parseable metadata file: ```python def _finalize_installed_pack(target_dir: Path) -> dict[str, str | bool]: meta_path = target_dir / "meta.json" if not meta_path.is_file(): shutil.rmtree(target_dir, ignore_errors=True) return { "ok": False, "message": "Installation failed: meta.json is missing.", } try: meta = json.loads(meta_path.read_text(encoding="utf-8")) except json.JSONDecodeError: shutil.rmtree(target_dir, ignore_errors=True) return { "ok": False, "message": "Installation failed: meta.json is invalid.", } ``` Instruction-bearing files are then loaded into the agent context: ```python role = self._render_section(name, "Role", "role") if role: sections.append( ...[truncated 2618 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/engram_server/loader.py:241
Finding

Memory Category Path Traversal Permits Arbitrary File Modification and Persistent Prompt Poisoning

Content
View full analysis
bool: if is_global: memory_dir = self._global_memory_dir() else: engram_dir = self._resolve_engram_dir(name) if engram_dir is None: return False memory_dir = engram_dir / "memory" memory_dir.mkdir(parents=True, exist_ok=True) entry = f"\n---\n{meta_line}\n{content.strip()}\n" category_file = memory_dir / f"{category}.md" try: with category_file.open("a", encoding="utf-8") as f: f.write(entry) except OSError: return False ``` The same unsafe category construction is used by consolidation: ```python memory_dir = engram_dir / "memory" category_file = memory_dir / f"{category}.md" archive_file = memory_dir / f"{category}-archive.md" ``` ### Technical Analysis The `category` value is caller-controlled but is used directly as part of a filesystem path. Unlike `write_file` and `add_knowledge`, this method does not: - Reject absolute paths. - Reject path separators. - Reject `.` or `..` components. - Resolve the resulting path. - Verify that the resolved target remains under `memory_dir`. For example, a category of `../rules` produces a target equivalent to `memory/../rules.md`, allowing the memory operation to append attacker-controlled content directly to the Engram's instruction file. An absolute category may cause the left-hand directory to be ...[truncated 1477 chars]
Remediation
View remediation

T02 · Agent Memory Poisoning

Error
Location
src/engram_server/server.py:545
Finding

Automatic Persistent Collection of Personal Data and Tool Traces Enables Memory Poisoning

Content
View full analysis
str: ok = loader.capture_memory( name, content, category, summary, memory_type=memory_type, tags=tags, conversation_id=conversation_id, expires=expires, is_global=is_global, ) ``` Stored memory is automatically returned during future loads: ```python if active_content: sections.append( f"## Dynamic Memory\n\n{active_content}\n" ) if active_global: sections.append( f"## Global User Memory\n\n" f"{''.join(active_global).strip()}\n" ) ``` ### Technical Analysis Persistent memory is a declared project feature, but the implementation and agent instructions use a ...[truncated 2072 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/engram_server/web.py:73
Finding

Unauthenticated Loopback Web UI Allows Cross-Origin Modification of Agent Instruction Files

Content
View full analysis
JSONResponse: loader: EngramLoader = request.app.state.loader name = request.path_params["name"] file_path = request.path_params["path"] body = await request.json() content = body.get("content", "") ok = loader.write_file(name, file_path, content) if not ok: return _json({"error": "Write failed"}, 400) return _json({"ok": True}) ``` The endpoint is exposed without authentication: ```python api_routes = [ Route("/engrams", api_list_engrams), Route("/engrams/{name}", api_get_engram), Route("/engrams/{name}/files", api_list_files), Route("/engrams/{name}/files/{path:path}", api_read_file, methods=["GET"]), Route("/engrams/{name}/files/{path:path}", api_write_file, methods=["PUT"]), Route("/engrams/{name}/memory", api_delete_memory, methods=["DELETE"]), Route("/engrams/{name}/lint", api_lint), Route("/stats", api_stats), ] ``` All origins, methods, and headers are allowed: ```python app = Starlette(routes=routes) app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"], ) app.state.loader = loader ``` ### Technical Analysis The UI binds to loopback, but loopback binding is not an authentication boundary. A webpage loaded from an attacker-controlled origin can attempt requests to services running on `127.0.0.1` or `localhost`. The application explicitly permits every origin, HTTP method, and header. The file-write and memory-delete endpoints have no authentication token, session validation, CSRF defense, or Origin verification. `loader.write_file` prevents traversal outside the selected Engram directory, but it intentionally permits writes t ...[truncated 1522 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (219)

Chaining Abuse

High
Category
Tool Misuse
Confidence
95% confidence
Finding

Piping remote content directly into a shell is a classic command-chaining abuse pattern because it collapses fetch and execution into one step with no validation barrier. In the context of an AI tool README, users may copy-paste this command blindly, giving any compromise of the script source immediate code execution.

Content

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

md
# macOS / Linux
brew install uv
# 或
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Ssd 3

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The recommended prompt tells the agent to persist user facts, preferences, decisions, and tool activity by default, including globally shared memory. In practice this creates a broad surveillance-like memory layer inside the agent that may accumulate sensitive personal or behavioral data without meaningful user awareness or boundaries.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

The example explicitly encourages storing identifying and potentially sensitive personal data such as name, age, city, occupation, language preference, and health conditions in shared global memory for reuse by all experts. This materially increases privacy and compliance risk because sensitive profile data is normalized as a reusable shared asset rather than tightly scoped context.

Content

No source excerpt is available for this finding.

Chaining Abuse

High
Category
Tool Misuse
Confidence
97% confidence
Finding

Piping network content directly into a shell is a chaining-abuse pattern because it collapses retrieval and execution into one step with no verification barrier. In security-sensitive tooling like an MCP server, this raises the chance that users will run compromised bootstrap code with their own privileges and then trust the installed agent thereafter.

Content

Scanner excerpt · README_en.md (reported line 119)May include surrounding context.

md
# macOS / Linux
brew install uv
# or
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The recommended system prompt directs the AI to proactively capture user facts, preferences, decisions, and global profile information, yet it does not require a user-facing notice or consent step before persistence. In an agent setting this can lead to covert collection and long-term storage of sensitive data across conversations and expert personas, increasing privacy, trust, and regulatory risk.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The global memory section explicitly instructs storing personal profile information once and replaying it across all experts. This broadens exposure across contexts and personas, making accidental disclosure, inappropriate reuse, or later compromise substantially more damaging than session-local memory.

Content

No source excerpt is available for this finding.

Agent Config Directory Access

High
Category
Agent Snooping
Confidence
90% confidence
Finding

Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Content

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

Claude Code

Project-level (.mcp.json in project root) or global (~/.claude/settings.json):

json
{

Agent Config Directory Access

High
Category
Agent Snooping
Confidence
90% confidence
Finding

Skill reads from agent configuration directories (.claude/, .codex/, .gemini/). These directories may contain API keys, personal settings, and other credentials that the skill has no legitimate need to access.

Content

Scanner excerpt · README_en.md (reported line 833)May include surrounding context.

Claude Code

Project-level (.mcp.json in project root) or global (~/.claude/settings.json):

json
{

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description says this skill is an MCP server for providing switchable expert memory to AI systems. However, the supplied code does not implement a server, MCP protocol handling, client integration, memory storage, retrieval, or persona/expert switching. Instead, it evaluates answer quality by matching expected and forbidden keywords, scoring checkpoints, assessing structure, comparing baseline and Engram responses, rendering a textual report, and optionally exporting CSV. This is a materially different primary purpose, so the description does not accurately represent the code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding

The declared description generally matches the core theme—this is indeed an Engram MCP server that lets AI clients use switchable expert-memory packs. However, the description significantly understates the code’s capabilities. Beyond merely 'injecting expert memory,' the code provides broad management and persistence features: it installs packs from remote sources via git, initializes and materializes packs on disk, edits files, captures and mutates long-term memory/tool-trace data, and can start a local web UI and open a browser. Declared permissions are empty, yet the code clearly performs filesystem writes, subprocess git cloning, network retrieval of registry/repositories, and browser/UI launch behavior. These are material undeclared capabilities rather than incidental implementation details, so this should be flagged as a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding

The declared description presents an MCP server whose purpose is to provide switchable expert memory to AI clients. The supplied code chunk does not implement or expose MCP server behavior, memory management, client integration, or expert-profile switching. Instead, it is a test harness for an evaluation script: it generates a case-study JSON file, invokes a scoring program, inspects textual scoring output, and validates a CSV report comparing baseline versus Engram answers. These behaviors are materially different from the declared primary purpose, so this chunk is mismatched with the description.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill explicitly directs the agent to capture and persist purchase history, complaints, product preferences, and contact preferences, including during onboarding, without any requirement to notify the user or obtain consent. In a brand-support context this is especially sensitive because the data is tied to customer identity and service history, creating privacy, compliance, and trust risks if stored unexpectedly or over-collected.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

High
Category
Not specified by scanner
Confidence
95% confidence
Finding

The description implies a fixed Japanese-speaking persona for several scenarios, which can override the user's preferred language or communication mode if the skill activates automatically. In an MCP/agent setting, this can degrade reliability, create unwanted prompt steering, and interfere with higher-priority user instructions because the behavior change occurs without clear opt-in.

Content

No source excerpt is available for this finding.

Possible Typosquatting: 'uvicorn' resembles popular package 'gunicorn'

High
Category
Supply Chain
Confidence
70% confidence
Finding

Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Content

No source excerpt is available for this finding.

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
80% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · src/engram_server/registry.py (reported line 121)May include surrounding context.

python
score += 12
            elif name_l.startswith(token):
                score += 8
            elif token in name_l:
                score += 6

            if token in tags_l:

Ssd 3

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The generated system prompt explicitly instructs the model to persist user preferences, personal facts, decisions, inferred details, and even global shared attributes across conversations. This is a real privacy and data-minimization risk because it encourages collection and long-term retention of sensitive user data without any consent gate, purpose limitation, or clear access-control boundary shown in this file.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The capture_memory tool is designed to store personal context, decisions, history, tags, conversation IDs, expiry metadata, and even global shared user attributes for reuse in future conversations. This creates a substantial privacy risk because the interface encourages durable storage of sensitive and inferred data without demonstrating consent checks, least-privilege access, or safeguards around cross-context sharing.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The file is written as mandatory operating instructions in Chinese and does not offer any user language or locale choice. This creates a natural-language policy concern if the skill behavior implicitly assumes or enforces Chinese-language interaction without opt-in or justification.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill maps broad, everyday phrases such as finding, recommending, installing, exporting, or opening a UI directly to MCP tool calls without requiring clear confirmation. That creates a real risk of unintended side effects, especially for install or write-capable actions, because normal conversation can be interpreted as authorization to invoke external tools automatically.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill instructs the agent to broadly capture personal facts, preferences, stateful information, and detailed tool traces, with persistence across conversations and optional global scope. This creates a substantial data retention and privacy risk because sensitive user information may be stored without necessity minimization, explicit consent, or strong scoping, and tool traces can leak confidential prompts, project details, or operational metadata.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The README advertises automatic capture of user preferences and key information, plus cross-expert shared global memory, without a clear consent notice, retention policy, or sensitivity boundaries. This can lead to collection and reuse of personal data users did not realize would be persisted and shared across contexts.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The design encourages broad retention and reuse of user-provided profile and preference data across sessions and experts. Centralizing such data increases the risk of privacy leakage, unintended secondary use, and oversharing into unrelated expert contexts.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
97% confidence
Finding

The README instructs users to run the MCP server via uvx --from git+https://... without pinning to a specific commit, tag, or immutable release. That causes every startup or install to trust the latest upstream repository state, so a compromised repo, malicious force-push, or hijacked dependency path could silently change code executed on the user's machine.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The recommended system prompt instructs the AI to automatically record all tool, MCP, subagent, and external tool activity, including failures, but does not clearly warn end users that these traces will be stored. Tool traces can contain sensitive arguments, filenames, prompts, or operational details that users may expect to remain ephemeral.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
97% confidence
Finding

This command launches code fetched directly from GitHub at runtime without a pinned version. In an MCP context, that is especially risky because the fetched code becomes a trusted local tool with access to project data and potentially sensitive prompts or files.

Content

No source excerpt is available for this finding.