Back to skill

Security audit

Memory Tree Pipeline

Security checks for vulnerabilities and agentic risk

Overview

This memory skill matches its stated purpose, but it needs Review because it persistently promotes stored content into reusable agent memory and has an unvalidated forget path that can delete markdown outside its topic folder.

Review before installing. Use this only with a dedicated memory workspace, avoid storing secrets or untrusted web/tool output unless you are comfortable with it becoming persistent agent context, and fix or constrain the forget operation before letting an agent call it automatically.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • 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)

T02 · Agent Memory Poisoning

Error
Location
scripts/tools.py:219
Finding

Untrusted Content Can Be Promoted into Persistent Agent Memory

Content
View full analysis
MAX_TOPIC_TOKENS: # Keep the newest content, truncate from the top new_content = _truncate_topic(new_content, MAX_TOPIC_TOKENS) topic_file.parent.mkdir(parents=True, exist_ok=True) topic_file.write_text(new_content, encoding="utf-8") ``` Topic content is then promoted into global memory: ```python # scripts/seal-worker.py:350-374 for topic_prefix in topic_prefixes: topic_file = TOPIC_DIR / f"{topic_prefix}.md" if topic_file.exists(): topic_content = topic_file.read_text(encoding="utf-8", errors="replace") # Extract just the key facts (headings + first lines) facts = _extract_key_facts(topic_content) if facts.strip(): combined += f"## {topic_prefix.title()}\n\n" combined += facts + "\n\n" if estimate_tokens(combined) > MAX_GLOBAL_TOKENS: combined = _truncate_global(combined, MAX_GLOBAL_TOKENS) if not dry_run: global_file.parent.mkdir(parents=True, exist_ok=True) ...[truncated 2517 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/tools.py:257
Finding

Path Traversal in Topic Deletion Can Remove Files Outside the Topic Directory

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (14)

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 · scripts/test_memory_tree.py (reported line 55)May include surrounding context.

python
- 2.198 SOL stolen through unauthorized withdrawals
- Attack vector: Telegram session compromise
- Lilo audit: our systems are CLEAN
- Security fixes applied: Gateway localhost, .env permissions

## Security Audit Results
- Network scan: all connections verified

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding

The skill advertises Python usage with a workspace path and memory operations that imply file reads/writes, but the manifest does not declare any tool scope or permissions boundaries. This creates ambiguity for hosts and reviewers about what capabilities the skill expects, increasing the risk of unintended filesystem or environment access when integrated into an agent framework.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The trigger phrase is very broad and includes generic terms like agent memory, structured memory, topic extraction, and summarization, which can cause the skill to activate in many unrelated contexts. Overbroad activation increases the chance that a skill with file and memory-management behavior is invoked unexpectedly, leading to unintended data processing or writes.

Content

No source excerpt is available for this finding.

Tainted flow: 'path' from os.environ.get (line 255, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/index-manager.py (reported line 51)May include surrounding context.

python
def save_json(path: Path, data):
    path.parent.mkdir(parents=True, exist_ok=True)
    with open(path, "w") as f:
        json.dump(data, f, indent=2, ensure_ascii=False)

Tainted flow: 'BACKUP_DIR' from os.environ.get (line 38, credential/environment) → shutil.copy2 (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/migrate-memory.py (reported line 362)May include surrounding context.

python
# Backup daily files
    for f in MEMORY_ROOT.glob("2*.md"):
        if f.parent == MEMORY_ROOT:
            shutil.copy2(f, BACKUP_DIR / f.name)

    # Backup other key files
    for name in ["backup.log", "d-drive-inventory.md", "heartbeat-state.json"]:

Tainted flow: 'src' from os.environ.get (line 366, credential/environment) → shutil.copy2 (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/migrate-memory.py (reported line 368)May include surrounding context.

python
for name in ["backup.log", "d-drive-inventory.md", "heartbeat-state.json"]:
        src = MEMORY_ROOT / name
        if src.exists():
            shutil.copy2(src, BACKUP_DIR / name)

    # Backup MEMORY.md
    if MEMORY_MD.exists():

Tainted flow: 'MEMORY_MD' from os.environ.get (line 33, credential/environment) → shutil.copy2 (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/migrate-memory.py (reported line 372)May include surrounding context.

python
# Backup MEMORY.md
    if MEMORY_MD.exists():
        shutil.copy2(MEMORY_MD, BACKUP_DIR / "MEMORY.md")

    # Backup .dreams directory
    dreams_dir = MEMORY_ROOT / ".dreams"

Tainted flow: 'index_file' from os.environ.get (line 409, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/migrate-memory.py (reported line 412)May include surrounding context.

python
index_file = META_DIR / "index.json"
        if not index_file.exists():
            import hashlib
            with open(index_file, "w") as f:
                json.dump(index, f, indent=2, ensure_ascii=False)
            print(f"Created index: {index_file}")

Ssd 3

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The worker copies source memory content into persistent topic summaries and then re-derives global knowledge from those summaries, which broadens storage and re-exposure of potentially sensitive data beyond the original source file. In an agent memory pipeline, this increases the chance that secrets, personal data, or sensitive operational details are retained longer, duplicated across files, and later surfaced to unrelated prompts or components.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The forget CLI path exposes deletion of topic summaries and, when --keep-source is not used, removal of associated source files with no confirmation prompt, dry-run, or other safety guard. In an agent-skill context, a model or automation invoking this tool with user-influenced input could cause unintended data loss in the configured memory workspace.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

The sample natural-language content specifies named English voices and marks one as the 'PRIMARY DEFAULT', which encodes a locale preference without indicating user choice or opt-in. Because SQP-3 applies to natural-language strings in any file type, this is a locale-policy concern even though it appears in test data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
93% confidence
Finding

The test helper unconditionally deletes the temporary test directory with shutil.rmtree, and similar deletion also occurs in setup_test_env at L156-L157. Although this is test code, the file's visible usage instructions do not warn that running the script will create and then recursively delete filesystem content under a temporary workspace.

Content

No source excerpt is available for this finding.

Dynamic attribute access via getattr()

Low
Category
Dangerous Code Execution
Confidence
50% confidence
Finding

Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.

Content

Scanner excerpt · scripts/test_memory_tree.py (reported line 180)May include surrounding context.

python
patches = {}
    for attr in ["MEMORY_ROOT", "SOURCE_DIR", "TOPIC_DIR", "GLOBAL_DIR", "META_DIR", "INDEX_FILE", "SEALING_LOG"]:
        if hasattr(mod, attr):
            patches[attr] = getattr(mod, attr)

    mod.MEMORY_ROOT = mem
    mod.SOURCE_DIR = mem / "source"

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
89% confidence
Finding

The test fixture text states 'Ryan primary. Thomas authority mode,' which hard-codes a language/locale-dependent voice preference in natural language. This can be read as forcing a specific locale/voice configuration rather than presenting it as optional or user-selected.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dynamic_code_execution

Dynamic code execution detected.

Critical
Code
suspicious.dynamic_code_execution
Location
scripts/test_memory_tree.py:27