T01 · Skill Instruction Hijacking
- Location
scripts/evolve.py:178- Finding
Indirect prompt injection can persist attacker-controlled procedure instructions
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This memory skill is purpose-aligned overall, but it needs Review because it persists broad agent memory, can send procedure history to configurable LLM endpoints, and can apply model-rewritten procedures without built-in approval.
Install only if you are comfortable with a local persistent memory database and review procedure evolution carefully. Prefer --dry-run for proc evolve, use a local or trusted LLM endpoint, avoid storing secrets in procedures/failure notes, do not put high-value API keys into brain.conf, and treat the multi-agent scope as organizational rather than a security boundary.
scripts/evolve.py:178Indirect prompt injection can persist attacker-controlled procedure instructions
scripts/evolve.py:224Configurable LLM endpoint can receive sensitive memory and bearer credentials
scripts/brain.sh:117LLM API keys are stored and printed in plaintext
scripts/brain.sh:8Caller-controlled and inconsistent agent scoping permits cross-agent access
scripts/schema.sql:72Documented fresh-install schema is incompatible with agent-aware runtime operations
The description presents a comprehensive, unified cognitive memory system with many subsystems and capabilities. The supplied code chunk, however, is narrowly focused on one subsystem: thalamic attention filtering. It computes heuristic attention scores and optionally queries a SQLite database to penalize recently similar episode content, but it does not implement the other major declared functions such as storing/retrieving memories, fact management, procedural evolution, consolidation, or health monitoring. This is a material description-to-behavior mismatch because the declared primary purpose is substantially broader than what the code actually does.
The declared description presents a broad, brain-inspired unified memory system with multiple subsystems and advanced capabilities: semantic fact management, procedural memory evolution, attention filtering, sleep consolidation, and health metrics. The supplied code chunk does not implement most of those capabilities. Instead, it is a narrow database operations helper that safely inserts episodes and performs parameterized searches/listings/statistics against SQLite tables. It does touch episodic recall and can search facts/procedures, so it partially aligns with the memory theme. However, the primary behavior here is CRUD/reporting for existing DB records, not the full unified cognitive system described. The mismatch is material because several highlighted capabilities are absent, and the command surface is a db_ops.py utility rather than the described consolidated brain command.
The declared description presents a comprehensive, brain-inspired unified memory platform with multiple subsystems and advanced behaviors. The supplied code only covers a narrow subset: semantic fact CRUD/search against a SQLite facts.db/facts_fts schema, plus simple statistics and access-count updates. It does not implement episodic memory, procedural memory, evolution, consolidation, filtering, or health metrics as described. The code also explicitly states it queries a legacy facts.db for backward compatibility, which contradicts the claim of a unified replacement system except in a limited subcommand sense. Therefore the description materially overstates the actual behavior of this code chunk.
The code chunk does relate to episodic memory storage, so it is thematically adjacent to the declared memory system. However, the actual code is not the unified cognitive memory system described. It specifically implements a one-off migration utility for importing daily markdown logs into an episodes table in a SQLite database. It does not provide semantic facts, procedural memory evolution, attention filtering, sleep consolidation, soul erosion metrics, or a unified brain command interface. Its primary purpose is data migration/import, which is a materially narrower and different capability than the declared system.
The declared description presents a broad, unified memory architecture spanning several distinct subsystems and capabilities. The supplied code chunk, however, is narrowly focused on working memory management: it parses TTLs, stores transient slots in SQLite, evicts low-priority items when capacity is exceeded, and synchronizes with a markdown session-state file. While this fits a plausible 'prefrontal cortex/working memory' component of a larger system, it does not implement or expose most of the declared features. This is a material description-behavior mismatch because the actual code’s primary purpose is much narrower than the declared skill purpose.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
## Key Feature: Procedure Evolution
Procedures that **rewrite themselves** from failure patterns:
1. Record failures with step-level granularity
2. At 3+ failures, the system suggests evolution
The README promotes LLM-driven procedure self-rewriting that can modify workflows based on observed failures, but it does not warn users that generated changes may be unsafe, incorrect, or manipulable by hostile inputs in stored failure data. In an agent skill that manages operational memory and procedures, this increases the chance of unsafe autonomous workflow drift, prompt-influenced procedure corruption, or accidental insertion of dangerous steps without human review.
The skill advertises capabilities that imply shell execution, filesystem access, environment-variable handling, database writes, and optional network egress to an LLM, but it declares no explicit tool scope or permissions boundary. In an agent ecosystem, this can cause the skill to be invoked with broader authority than users expect, increasing the chance of unintended file modification, secret exposure, or external data transmission.
The invocation guidance is extremely broad—covering storing experiences, recalling memories, managing facts, evolving procedures, filtering information, consolidation, and health checks—which makes the skill likely to be auto-selected for many generic prompts. In an agent system, overbroad routing increases the chance this skill gains access to sensitive user context, local files, databases, or optional LLM egress when a narrower or safer skill should have been chosen.
The manifest describes a unified cognitive memory system for storing, recalling, consolidating, and evolving memories/procedures. In this shell entrypoint, the config subcommand manages external LLM endpoint URLs and API keys, which is a distinct capability centered on configuring remote model access rather than directly performing memory operations. While LLM use is mentioned for procedural evolution, exposing generic endpoint and credential management at the CLI level is broader than the manifest's stated user-facing purpose.
The config set command writes arbitrary values, including API keys, to brain.conf on disk and then echoes the full value back to the terminal. This can expose secrets through shell history, terminal logs, screenshots, or other local observation, and storing credentials unencrypted in a skill directory increases the chance of accidental disclosure.
The module docstring states that low-value old episodes may be forgotten/archived as part of consolidation. However, in the forgetting section the code merely inserts a row into consolidation_log and explicitly comments that it does not delete or mark the episode, so the documented behavior contradicts the actual implementation.
The consolidation pipeline extracts data from free-form episode content and persists it into the facts table automatically, potentially duplicating secrets, personal data, incident details, URLs, or internal versions into a second long-lived store. In a memory skill whose purpose is broad retention and recall, this increases exposure surface, makes later retrieval more likely, and can undermine data minimization or deletion expectations.
The stats command runs aggregate queries over the entire database without applying the agent scope used elsewhere in the file. Any caller able to invoke this command can learn global counts, date ranges, emotion distributions, and activity patterns for other agents, which is a confidentiality and tenant-isolation failure in a multi-agent memory system.
The who command enumerates every agent present in episodes, facts, and procedures and reports per-agent record counts. In a system described as a memory store, this reveals tenant identities and metadata unrelated to the caller's authorized scope, enabling reconnaissance about other users or agents even if direct record access is otherwise restricted.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
# BRAIN_LLM_MODEL — Model name to use for evolution
#
# Supported providers (just point URL + key at any OpenAI-compatible API):
# - OpenAI: https://api.openai.com/v1/chat/completions + OPENAI_API_KEY
# - Anthropic: (via proxy)
# - Google: https://generativelanguage.googleapis.com/v1beta/openai/chat/completions + BRAIN_LLM_KEY
# - Ollama: http://localhost:11434/v1/chat/completions (no key needed)
Failure descriptions and fix_applied fields are treated as trusted context and fed back into the LLM, which then rewrites stored procedures. An attacker who can record crafted failures or fixes can gradually poison procedure evolution, causing harmful, misleading, or insecure steps to be persisted for future runs.
The evolve path sends full procedure content plus failure history and fixes to a configurable remote LLM endpoint. That creates a real confidentiality and trust-boundary issue: procedures, operational errors, and remediation notes may contain sensitive internal details and are transmitted off-host without minimization or strong allowlisting of destinations.
The script performs network transmission of procedure data to an external LLM without an explicit user-facing notice at runtime. In a memory/procedure tool, users may reasonably expect local handling, so silent upload of history and fixes increases privacy, compliance, and data-handling risk.
This code opens a SQLite database and inserts episode records derived from markdown daily logs, which likely contain personal or sensitive content. Although the script has a generic module docstring, it does not provide a user-facing warning or confirmation before persisting that data to the database in non-dry-run mode.
The script takes SESSION_STATE directly from an environment variable and uses it as a write path without validation. An attacker who can influence the environment can redirect writes to arbitrary files accessible to the process, causing file overwrite, data corruption, or clobbering of other application state; the risk is increased because this skill is explicitly designed to persist and sync memory state automatically.
output = "\n".join(lines)
with open(SESSION_STATE, "w") as f:
f.write(output)
print(f"✅ Dumped {len(rows)} working memory slots to SESSION-STATE.md")
The manifest describes cognitive memory features like episodic, semantic, procedural, attention, consolidation, and health metrics, but does not mention reading from or writing to a separate markdown session-state file. The wm help text and dispatcher explicitly support load, dump, and sync operations with SESSION-STATE.md, which is an extra integration capability beyond the declared purpose of the brain database/CLI.
The printed summary implies the forgetting/archive step changed episode state. But the only write in that path is to consolidation_log, and the nearby comment confirms the code does not actually archive the episodes.
This code path inserts user-supplied content into the SQLite database and commits it, which is a file-backed data write. While the module docstring describes database operations generally, this command lacks a user-facing warning or disclosure that the provided content will be persisted to the local brain database.
The cmd_recall docstring says 'Search all memory,' which implies unrestricted search across the brain. In practice, the function filters by agent_scope() to own+shared entries, so the inline documentation overstates what the command actually returns.
No suspicious patterns detected.