Back to skill

Security audit

Strategy Constitutional Memory

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly purpose-aligned, but it stores arbitrary lesson text and later tells users to place that text directly into an LLM system prompt, creating persistent prompt-influence risk.

Install only if you trust the people and automation that can write to its memory files. Treat stored lessons as untrusted records unless reviewed, keep the memory directory scoped to the project, inspect lessons.json and bans.json regularly, and avoid placing unreviewed imported text directly into a system prompt.

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

T02 · Agent Memory Poisoning

Error
Location
memory_system.py:86
Finding

Persistent LLM Prompt Injection Through Constitutional Memory

Content
View full analysis

Vulnerability Details

File Location: memory_system.py:86-112, 267-306; related input and usage guidance at cli.py:66-79, 119-127 and SKILL.md:77-79, 136-140
Vulnerability Type: Persistent agent-memory poisoning leading to prompt injection
Risk Level: High

Complete Code Snippet

The CLI accepts arbitrary lesson content:

python
add.add_argument("--strategy", required=True, help="Strategy identifier")
add.add_argument(
    "--category",
    required=True,
    help="Category (e.g. drawdown, selection, position_sizing, timing, ml_failure, success)",
)
add.add_argument("--description", required=True, help="Root-cause description")
add.add_argument("--evidence", default="", help="Supporting data / evidence")

The content is persisted without trust validation:

python
lesson = {
    "id": len(self.lessons) + 1,
    "timestamp": datetime.now().isoformat(),
    "strategy": strategy_name,
    "category": category,
    "description": description,
    "evidence": evidence,
    "severity": severity,
}
self.lessons.append(lesson)

if new_ban and new_ban not in self.bans:
    self.bans.append(new_ban)

self._save()

The stored values are subsequently interpolated verbatim into LLM context:

python
for lesson in sorted_lessons:
    label = SEVERITY_LABELS.get(lesson["severity"], "[INFO]")
    lines.append(
        f"{label} [{lesson['strategy']}] {lesson['category']}: "
        f"{lesson['description']}"
    )
    if lesson.get("evidence"):
        lines.append(f"  Evidence: {lesson['evidence']}")

lines.append(f"\n=== Banned Code Patterns ({len(self.bans)} total) ===")
for ban in self.bans:
    lines.append(f"  X Prohibited: `{ban}`")

return "\n".join(lines)

The documentation instructs consumers to use this generated text as prompt material:

markdown
context = memory.get_context(max_lessons=30)
# Returns formatted text with lessons sorted by severity,
# banned patterns list, verified blueprints, and core rules
markd
...[truncated 2823 chars]
Remediation
View remediation

Remediation Suggestions

  1. Separate policy from observations

    • Store administrator-approved constitutional rules separately from user-supplied lessons and diagnostic evidence.
    • Never promote untrusted observations into authoritative prompt instructions automatically.
  2. Use structured, explicitly untrusted context

    • Supply lessons as structured data rather than concatenating them into the system prompt.
    • Delimit the data and add a higher-priority instruction stating that stored entries are historical records, not executable instructions.
    • Ensure downstream prompt templates do not characterize unreviewed content as mandatory policy.
  3. Add validation and normalization

    • Enforce allowlists for categories and severity values in both the API and CLI.
    • Apply reasonable length limits to all fields.
    • Detect or quarantine instruction-like content, prompt-role markers, and attempts to override prior rules.
    • Validate JSON types and schemas when loading persisted files.
  4. Introduce provenance and approval controls

    • Record the source and author of each lesson.
    • Require trusted review before a lesson or ban becomes prompt-visible.
    • Consider signing approved memory records and rejecting records with invalid signatures.
  5. Protect memory integrity

    • Restrict filesystem permissions on the memory directory.
    • Use atomic writes and integrity checks.
    • Provide quarantine, rollback, and deletion mechanisms for poisoned entries, notwithstanding the current append-only guidance.
  6. Apply least privilege downstream

    • Require independent policy enforcement before executing code or actions generated by the LLM.
    • Do not rely on prompt instructions alone to enforce prohibited operations.
Vulnerability Patterns
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (1)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding

The skill describes persistent writes to local files such as memory/lessons.json and memory/bans.json, but it does not declare any explicit tool scope or permissions for file-writing behavior. Undeclared write capability is risky because an agent or host may execute the skill with broader filesystem access than reviewers expect, enabling unintended modification of project files or persistent state without clear authorization boundaries.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.