Back to skill

Security audit

Mem Skill

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent local memory tool, but it asks to run across ordinary tasks and persist conversation-derived data with more authority and less containment than users should accept without review.

Install only if you intentionally want an always-on workspace memory layer. Keep it out of shared or sensitive workspaces unless you audit and periodically clear knowledge-base, experience, and log.md. Avoid QMD/global setup and URL ingestion until dependencies are pinned, the init.sh path-injection bug is fixed, and retention/redaction controls are added.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

T01 · Skill Instruction Hijacking

Error
Location
SKILL.md:285
Finding
Global Agent Behavior and Output Hijacking<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:3`, `SKILL.md:285-287`, `SKILL.md:313-339`, and `SKILL.md:391-392` **Vulnerability Type**: Mandatory cross-task instruction hijacking **Risk Level**: High ### Vulnerable Code ```markdown description: "Self-evolving memory and knowledge accumulation system for AI agents. Acts as a persistent 'second brain' that automatically retrieves past experiences, captures best practices, and proactively records successful solutions to a private knowledge base. Use this skill whenever starting any task, opening a new conversation, or triggering any other skill." ``` ```markdown ## Core Loop (Mandatory Every Turn) Execute these steps on every conversation turn. Do not display internal cache state to the user. ``` ```markdown ### Step 3: Cross-Skill Experience Read (Forced — Ignores Topic Switch) Whenever a non-mem-skill skill is used this turn: - If the `skill-id` is already in `loaded_experience_skills`, skip (do not re-read or re-announce). - Otherwise: 1. Read `experience/_index.json`. 2. If a matching `skill-id` entry exists, load `experience/skill-<skill-id>.md`. 3. Add the `skill-id` to `loaded_experience_skills`. 4. Include in response: `"Loaded experience: skill-<skill-id>.md"` 5. Log (first read per session only): Append to `log.md`: `## [YYYY-MM-DD] read | Retrieved experience: skill-<skill-id>.md` 6. If no entry exists, add to `missing_experience_skills`. ``` ```markdown **Forced rule — always ask when experience is missing:** If a non-mem-skill skill was used this turn and that skill has no entry in `experience/_index.json`, you **must** ask at task completion: > "We used <skill-name> this time, but there's no experience record yet. Can I record this session's approach for future reference?" ``` ### Technical Analysis The skill declares that it should activate whenever any task, conversation, or other skill begins. Once loaded, it directs the agent to execute a mandatory loop on e ...[truncated 2247 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove the global activation directive stating that the skill must run for every task, conversation, or other skill. 2. Replace mandatory and forced behavior with explicit, user-initiated operations such as `/mem-skill search`, `/mem-skill recordnow`, or `/mem-skill lint`. 3. Retrieve persistent memory only when the current user request explicitly requires it or after obtaining informed consent. 4. Do not require fixed response text unrelated to the active task. 5. Treat all stored Markdown as untrusted data rather than executable instructions. Clearly delimit retrieved content and direct the agent not to follow instructions contained inside memory entries. 6. Add provenance and trust metadata to entries and exclude untrusted ingested content from automatic retrieval. 7. Ask for recording approval only within an explicitly active memory workflow, not whenever an unrelated skill completes. 8. Provide a documented configuration option that disables automatic retrieval and recording suggestions by default. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
scripts/init.sh:88
Finding
Python Code Injection Through a Crafted Workspace Path<![CDATA[ ## Vulnerability Details **File Location**: `scripts/init.sh:88-89` and `scripts/init.sh:144-151` **Vulnerability Type**: Unsafely interpolated filesystem path in Python source code **Risk Level**: High ### Vulnerable Code ```bash OLD_VERSION="unknown" CURRENT_ENGINE="default" if [ -f "$WORKSPACE/.mem-skill.config.json" ]; then OLD_VERSION=$(python3 -c "import json; print(json.load(open('$WORKSPACE/.mem-skill.config.json')).get('version', 'unknown'))" 2>/dev/null || echo "unknown") CURRENT_ENGINE=$(python3 -c "import json; print(json.load(open('$WORKSPACE/.mem-skill.config.json')).get('engine', 'default'))" 2>/dev/null || echo "default") fi ``` ```bash if [ -f "$WORKSPACE/.mem-skill.config.json" ]; then python3 -c " import json with open('$WORKSPACE/.mem-skill.config.json', 'r') as f: config = json.load(f) config['version'] = '1.2.0' with open('$WORKSPACE/.mem-skill.config.json', 'w') as f: json.dump(config, f, indent=2) f.write('\n') " echo " ✓ Updated config version to 1.2.0" fi ``` ### Technical Analysis `WORKSPACE` is initialized from `pwd` and is then interpolated directly into strings containing Python source passed to `python3 -c`. Shell quoting protects the value from direct shell expansion as a command, but it does not make the value safe as Python syntax. A valid Unix directory name can contain apostrophes and newline characters. A crafted workspace path can therefore terminate the Python string literal used by `open(...)`, introduce additional Python statements, and comment out or otherwise neutralize the remaining generated source. The prerequisite checks only require the crafted workspace to contain: - `knowledge-base/_index.json` - `experience/_index.json` - `.mem-skill.config.json` for the vulnerable Python invocations The script executes the injected Python with the same privileges as the user running `init.sh --upgrade`. ### Attack Path 1. An attacker prepares or distributes a project whose directory n ...[truncated 1624 chars]
Remediation
<![CDATA[ ## Remediation Suggestions Pass the configuration path as a separate argument instead of embedding it in Python source: ```bash CONFIG_PATH="$WORKSPACE/.mem-skill.config.json" OLD_VERSION=$( python3 -c ' import json import sys with open(sys.argv[1], "r", encoding="utf-8") as f: print(json.load(f).get("version", "unknown")) ' "$CONFIG_PATH" 2>/dev/null || echo "unknown" ) CURRENT_ENGINE=$( python3 -c ' import json import sys with open(sys.argv[1], "r", encoding="utf-8") as f: print(json.load(f).get("engine", "default")) ' "$CONFIG_PATH" 2>/dev/null || echo "default" ) ``` Update the configuration in the same way: ```bash python3 - "$CONFIG_PATH" <<'PY' import json import sys path = sys.argv[1] with open(path, "r", encoding="utf-8") as f: config = json.load(f) config["version"] = "1.2.0" with open(path, "w", encoding="utf-8") as f: json.dump(config, f, indent=2) f.write("\n") PY ``` Additional hardening should include: 1. Use an environment variable or `sys.argv` for every value crossing from Bash into Python. 2. Never construct Python, shell, SQL, or another interpreter's source code through string interpolation. 3. Add automated tests using workspace names containing apostrophes, quotes, spaces, newlines, Unicode characters, and shell metacharacters. 4. Write configuration updates to a temporary file in the same directory and atomically rename it after successful validation. 5. Validate that the parsed configuration is a JSON object and that expected fields contain allowed values. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/init.sh:238
Finding
Unpinned Global Installation of a Third-Party NPM Package<![CDATA[ ## Vulnerability Details **File Location**: `scripts/init.sh:238-250` **Additional References**: `SKILL.md:51-53` and `references/qmd-engine.md:17,32` **Vulnerability Type**: Unpinned global dependency installation **Risk Level**: Medium ### Vulnerable Code ```bash # Check if QMD is installed if ! command -v qmd &> /dev/null; then echo "" echo " QMD is not installed." echo " Install with: npm install -g @tobilu/qmd" echo " Requires: Node.js >= 22" echo "" read -p " Install QMD now? (y/N) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then npm install -g @tobilu/qmd else echo " Skipping QMD installation. You can install it later and re-run init." exit 1 fi fi ``` The same unpinned command is prescribed in the skill documentation: ```markdown QMD is not installed. Install it now with `npm install -g @tobilu/qmd`? ``` ### Technical Analysis The setup installs the latest registry version of `@tobilu/qmd` globally without a version constraint, lockfile, integrity hash, or artifact verification. Although the script asks for confirmation, approval only confirms the general installation; it does not establish which immutable package version or transitive dependency set will be executed. NPM package installation may run package lifecycle scripts. Consequently, a compromised maintainer account, malicious future release, registry compromise, or compromised transitive dependency could execute code during installation. Global installation also broadens the effect beyond this project and can replace or alter the `qmd` command used by other workspaces. No evidence was found that the currently referenced package is malicious. The vulnerability is the unsafe and non-reproducible dependency acquisition process. ### Attack Path 1. The user selects the QMD engine. 2. The script determines that `qmd` is not currently available. 3. The user approves the installation prompt. 4. NPM resolves the current registry release o ...[truncated 1145 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin QMD to a specifically reviewed version: ```bash npm install --save-exact @tobilu/qmd@REVIEWED_VERSION ``` 2. Prefer a project-local dependency instead of a global installation, then invoke it through a locked package script or an equivalent local binary path. 3. Commit and verify a lockfile so the complete transitive dependency graph is reproducible. 4. Use registry integrity metadata and verify package provenance or signatures where supported. 5. Document the exact reviewed package version and update it only through a controlled dependency-review process. 6. Do not automatically install dependencies from within the skill. Instead, display the pinned command and require the user to perform the installation separately. 7. Consider initially installing with lifecycle scripts disabled where compatible: ```bash npm install --ignore-scripts --save-exact @tobilu/qmd@REVIEWED_VERSION ``` If lifecycle scripts are required, review them before enabling installation. 8. Execute QMD in a least-privileged environment and avoid running the setup as root or through `sudo`. 9. Validate the resolved executable path and expected version before invoking `qmd`. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (22)

Vague Triggers

High
Confidence
98% confidence
Finding
The instruction to use this skill whenever starting any task, opening a new conversation, or triggering any other skill gives it extremely broad activation scope. In context, that broad scope is dangerous because the skill persistently reads, logs, and may propose recording conversation-derived data across ordinary workflows without a narrowly defined user request.

Vague Triggers

High
Confidence
97% confidence
Finding
The 'Core Loop (Mandatory Every Turn)' requires memory-related processing on every conversation turn, including keyword extraction, topic tracking, and conditional file reads/logging. This is overbroad for a persistence skill and increases the chance of non-consensual monitoring, unnecessary data retention, and accidental interaction with sensitive conversations.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The script can run `npm install -g @tobilu/qmd`, which installs software globally on the host. Global package installation is a high-risk capability for a memory skill because it changes the system outside the workspace, can introduce supply-chain compromise, and may require elevated privileges or affect other projects and users.

Session Persistence

Medium
Category
Rogue Agent
Content
You just ask for what you need. mem-skill reads the knowledge base automatically:

```
You:   Help me write a simple landing page about NVDA stock introduction
Agent: [reads knowledge-base/_index.json — looking for matching categories]
       ...builds the page...
       Created nvda-landing.html
Confidence
90% confidence
Finding
Automatically reading a persistent knowledge base on ordinary user requests creates cross-session persistence and context carryover. In a shared workspace, this can expose prior users' stored preferences, project details, or sensitive notes to unrelated future conversations, especially since the skill markets itself as a reusable 'second brain.'

Ssd 3

Medium
Confidence
96% confidence
Finding
The skill is explicitly designed to persist conversationally derived knowledge, activity logs, and workspace memory over time, including for future users of the same workspace. In a shared or sensitive environment, this creates a substantial data retention and cross-session disclosure risk because secrets, proprietary context, or personal data can be stored in plain language and later surfaced unintentionally.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
## Real-World Example: QMD Engine

Same workflow, but with semantic search powered by QMD. The key differences: you pass flags to skip prompts, and retrieval uses `qmd query` instead of JSON keyword matching.

### 1. Initialize with Flags
Confidence
85% 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.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Ssd 3

Medium
Confidence
97% confidence
Finding
The `recordnow` behavior scans the full conversation and extracts items for long-term storage. Full-conversation review is dangerous because users often include credentials, internal URLs, personal data, or confidential business context that may be captured incidentally and later retrieved out of context.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
This prevents one project's collections from overwriting another's.

#### Skip Prompts with Flags

Pass `--qmd-*` flags to pre-configure everything in one command:
Confidence
85% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  Step 1: Extract Keywords                                        │
│     "help me write a landing page about NVDA stock"              │
│     → keywords: [landing-page, NVDA, stock, HTML, introduction]  │
│                                                                  │
│  Step 2: Detect Topic Switch                                     │
Confidence
91% confidence
Finding
The core loop explicitly extracts keywords from each turn and uses them to drive retrieval from persistent memory. That design increases the chance that future prompts trigger exposure of previously stored sensitive material based on topical similarity, even when the current user did not intend to access historical data.

Ssd 3

Medium
Confidence
95% confidence
Finding
The documented core loop normalizes ongoing logging and storage of conversation-derived knowledge and operational history. Because these artifacts are plain-language files in the workspace, they can accumulate sensitive data over time and become accessible to later tasks, other users, or other tools with workspace access.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill instructs the agent to read and write multiple workspace files, but the manifest does not declare any explicit tool scope or file access boundaries. That makes the effective access ambiguous and increases the risk of unintended reads/writes across the workspace, especially because the skill also says it should run broadly and every turn.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The description strongly encourages broad use but does not prominently warn that the skill persistently stores conversation-derived data, user preferences, skill activity, and workspace content. Users may therefore activate it without informed consent about retention and local logging effects.

Rp1

Medium
Category
MCP Rug Pull
Confidence
84% confidence
Finding
The skill relies on `npx @tobilu/qmd status`, which can resolve and execute code without a pinned version, making behavior non-reproducible and exposing users to supply-chain risk if the package changes or is compromised. Because this is part of an initialization flow, users may run it with little scrutiny.

Context-Inappropriate Capability

Medium
Confidence
88% confidence
Finding
The QMD flow invokes system and package-management commands such as `which`, `npx`, `npm install -g`, and later `qmd` operations. For a memory skill, these commands significantly increase capability and attack surface, especially when paired with broad invocation guidance and persistent storage behaviors.

Ssd 3

Medium
Confidence
93% confidence
Finding
The manual recording flow instructs the agent to review the full conversation history and persist summarized task information into local memory and logs. That creates a clear risk of retaining sensitive user content, secrets, or contextual details beyond the immediate session, especially if the user does not realize the breadth of what may be recorded.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The skill is presented as a private workspace memory system, but it also supports ingesting arbitrary URLs and fetching remote content. That expands the trust boundary from local private data to untrusted network input, creating privacy, prompt-injection, and data-mixing risks that are not obvious from the skill description.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The URL ingest feature fetches external content, but the documentation does not clearly warn about network access, privacy implications, or the risks of processing untrusted remote data. This can surprise users who believed the skill was confined to local private workspace memory.

Ssd 3

Medium
Confidence
90% confidence
Finding
The ingest workflow extracts and reformats content from local files, directories, or URLs into persistent knowledge entries. Without stronger consent and filtering boundaries, this can copy sensitive proprietary or personal data into a long-lived knowledge base, broadening exposure and retention.

Ssd 3

Medium
Confidence
95% confidence
Finding
The mandatory every-turn memory flow continuously derives keywords, tracks prior inputs and skill usage, reads stored knowledge, and may log retrieval activity. Even when not overtly malicious, this establishes persistent behavioral tracking and reuse of conversation-derived data that can exceed user expectations and increase privacy exposure.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The init script goes beyond creating local workspace files and performs external dependency checks, optional package installation, and QMD operations that can modify global state or contact external services. In a skill that is supposed to initialize a memory workspace, this expands trust boundaries and creates supply-chain and unintended side-effect risk, especially because users may run it routinely at the start of many tasks.

Static analysis

No suspicious patterns detected.