Back to skill

Security audit

hippocampus

Security checks for vulnerabilities and agentic risk

Overview

This is a local memory skill, but it automatically stores and reuses conversation history across sessions with broad triggers and scheduled-job setup that users should review carefully.

Install only if you intentionally want long-term local memory. Before enabling it, consider disabling AUTO_SAVE, proactive triggers, ReadingBetweenTheLines, cron jobs, and session hooks until you understand exactly what will be stored and recalled. Avoid using it with secrets, credentials, private customer data, or confidential conversations unless you add your own retention, review, and deletion process.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (3)

T02 · Agent Memory Poisoning

Error
Location
scripts/memory.py:1191
Finding
Persistent Prompt Injection Through Proactive Memory Recall<![CDATA[ ## Vulnerability Details **File Location**: `scripts/memory.py:1191-1199`, with persistence paths at `scripts/memory.py:1500-1529` **Vulnerability Type**: Persistent memory poisoning and cross-session prompt injection **Risk Level**: High ### Vulnerable Code ```python # === Proactive trigger: load relevant memory if keyword found === proactive = context.get("proactive_message", "") if proactive: proactive_content = get_proactive_memory(proactive) if proactive_content: # Prepend proactive memory to context for this turn ctx = dict(context) ctx["content"] = ( proactive_content + "\n\n" + ctx.get("content", "") ).strip() context = ctx ``` Conversation history can also be persisted automatically: ```python # Get content from context content = "" if context and 'content' in context: content = context.get('content', '') elif context and 'history' in context: # Try to get from history history = context.get('history', []) if history: content = "\n".join([str(h) for h in history[-20:]]) if not content: return "No content to check" token_count = len(content) round_count = context.get('round_count', 0) if context else 0 trigger_type = self.check_trigger(round_count, token_count) if trigger_type: threshold = config.get('TOKEN_THRESHOLD', 10000) if token_count > threshold: topic = context.get('topic', 'General') if context else 'General' save_monograph(topic, content, token_count) result = ( f"Auto-saved to Monograph " f"(trigger: {trigger_type}, tokens: {token_count})" ) else: save_chronicle(content) result = ( f"Auto-saved to Chronicle " f"(trigger: {trigger_type}, tokens: {token_count})" ) ``` ### Technical Analysis The Skill stores raw session context and recent history without preserving a meaningful trust boundary between user instructions, external ...[truncated 2319 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store role, source, session, and trust metadata with every memory record. 2. Treat all recalled content as untrusted reference material rather than executable instructions. 3. Wrap recalled data in explicit delimiters and prepend a trusted directive stating that instructions inside the recalled material must not be followed. 4. Exclude external content, tool output, and system messages from automatic storage unless explicitly approved. 5. Detect and quarantine instruction-like phrases before allowing proactive recall. 6. Require explicit user approval before inserting recalled content into the active Agent context. 7. Return recalled memory through a structured data field rather than concatenating it into the main instruction-bearing context. 8. Disable proactive triggers by default and require per-topic opt-in. 9. Add controls to inspect, edit, quarantine, and securely delete poisoned memory records. 10. Test the recall path with stored prompt-injection payloads to verify that they are rendered only as inert data. ]]>

T06 · System Persistence

Error
Location
scripts/memory.py:1813
Finding
Cross-Session Persistence Through Scheduled Jobs and Session Hooks<![CDATA[ ## Vulnerability Details **File Location**: `scripts/memory.py:1813-1824`, `scripts/memory.py:1963-1981`, and `scripts/memory.py:1991-2017` **Vulnerability Type**: Persistent scheduled execution and lifecycle-hook registration **Risk Level**: High ### Vulnerable Code The Skill generates recurring cron-job setup instructions: ```python def _cmd_setup_hooks(self) -> str: """Generate cron/hook setup commands""" skill_path = str(SKILL_DIR) return f"""# Add these cron jobs for automatic memory saving: # 1. Time-based trigger (every {get_config().get('TIME_HOURS', 6)} hours) cron add --name "hippocampus-autosave-time" \ --schedule "0 */{get_config().get('TIME_HOURS', 6)} * * *" \ --session-target isolated \ --payload 'Run: python3 {skill_path}/scripts/memory.py autocheck' # 2. Session end hook (automatic save on session close) # Note: This requires OpenClaw hook configuration # Alternative: Use heartbeat to trigger periodic checks # Run this command to test: python3 {skill_path}/scripts/memory.py autocheck """ ``` It also generates commands for three recurring tasks: ```python return f"""# Execute these cron job creations: ## 1. Auto-save (every 6 hours) ``` cron add --name "hippocampus-autosave" --schedule "0 */6 * * *" --session-target isolated --payload "Run: python3 {skill_path}/scripts/memory.py autocheck" --delivery-mode none ``` ## 2. Daily-create (midnight) ``` cron add --name "hippocampus-daily-create" --schedule "0 0 * * *" --session-target isolated --payload "Run: echo \\"$(date +%Y-%m-%d)\\"" --delivery-mode none ``` ## 3. Daily-analyze (23:00) ``` cron add --name "hippocampus-analyze" --schedule "0 23 * * *" --session-target isolated --payload "Run: python3 {skill_path}/scripts/memory.py analyze" --delivery-mode none ``` """ ``` A session-end hook is also proposed: ```python return f"""# Hook Configuration ## Required Configuration To enable automatic memory save on session end, add this to your `{config_path}`: ...[truncated 2656 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Keep all scheduled execution and session hooks disabled by default. 2. Separate optional automation setup from core installation and on-demand memory functionality. 3. Require explicit, informed consent that identifies the exact schedule, command, accessed data, retention policy, and removal procedure. 4. Prefer a constrained, platform-managed event API over shell-like cron payloads. 5. Pin scheduled tasks to an immutable or integrity-verified Skill version. 6. Limit hooks to narrowly scoped structured data instead of complete session context. 7. Provide commands that list and remove every cron job and lifecycle hook created by the Skill. 8. Display persistent automation status prominently in `/hippo status`. 9. Avoid allowing generic confirmations such as `yes` to authorize system-level persistence unless tied to a specific pending action. 10. Reconfirm authorization after upgrades or material configuration changes. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/memory.py:853
Finding
Automatic Indefinite Plaintext Storage of Sensitive Conversation Content<![CDATA[ ## Vulnerability Details **File Location**: `scripts/memory.py:853-902`, `scripts/memory.py:933-1011`, and `USER_CONFIG.md:35-39` **Vulnerability Type**: Sensitive information stored in plaintext without retention or redaction controls **Risk Level**: Medium ### Vulnerable Code Chronicle records embed the complete supplied content in a plaintext Markdown file: ```python def save_chronicle(content: str, session_id: str = None) -> str: """Save temporal memory to Chronicle""" _lazy_init() config = get_config() extractor = KeywordExtractor() keywords = extractor.extract(content) timestamp = datetime.now().strftime("%Y-%m-%d-%H-%M") date = datetime.now().strftime("%Y-%m-%d") filename = f"{timestamp}.md" filepath = get_chronicle_path() / filename keyword_str = ",".join( list(keywords["word_frequency"].keys())[:10] ) md_content = f"""# Chronicle - {date} ## Metadata - **Timestamp**: {timestamp} - **Session**: {session_id or 'N/A'} - **Keywords**: {keyword_str} ## Content {content} ## Analysis | Keyword | Frequency | |---------|-----------| """ for kw, cnt in list(keywords["word_frequency"].items())[:15]: md_content += f"| {kw} | {cnt} |\n" filepath.write_text(md_content, encoding='utf-8') conn = sqlite3.connect(str(get_db_path())) cursor = conn.cursor() cursor.execute(''' INSERT INTO chronicle_index (file_name, file_path, timestamp, date, keywords, content_preview, session_id, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ''', ( filename, str(filepath), timestamp, date, keyword_str, content[:200], session_id, datetime.now().isoformat() )) conn.commit() conn.close() return str(filepath) ``` Monograph records use the same plaintext design: ```python md_content = f"""# {topic} ## Metadata - **Created**: {datetime.now().isoformat()} - **User**: {meta.ge ...[truncated 3078 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Disable automatic saving by default and require explicit opt-in. 2. Minimize stored content; prefer user-selected summaries over complete transcripts. 3. Detect and redact common secrets, including API keys, access tokens, passwords, private keys, authorization headers, and connection strings. 4. Encrypt sensitive records at rest with keys managed separately from the Skill directory. 5. Create files and directories with restrictive owner-only permissions. 6. Introduce configurable retention periods, storage quotas, and automatic expiration. 7. Provide commands to review, export, delete, and securely purge individual records or all stored memory. 8. Avoid storing content previews in SQLite when the complete record is already present elsewhere. 9. Clearly disclose what data will be stored before enabling session-end hooks or recurring autosave. 10. Add automated tests confirming that representative credential formats are redacted and expired records are removed. ]]>
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 Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (31)

Ae1

High
Category
analysis-evasion
Content
python3 scripts/memory.py init
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Ae1

High
Category
analysis-evasion
Content
python3 scripts/memory.py init
Confidence
100% confidence
Finding
Referenced artifact was not completely inspected

Vague Triggers

High
Confidence
95% confidence
Finding
The ReadingBetweenTheLines feature performs autonomous memory loading based on repeated topic discussion in a sliding window, which is a broad behavioral trigger rather than an explicit user command. This substantially increases the chance of prompt-context poisoning, unintentional retrieval of sensitive material, and manipulation by an attacker who can steer conversation toward trigger thresholds to force memory injection.

Vague Triggers

High
Confidence
96% confidence
Finding
The trigger list includes very common words such as 'remember', 'recall', 'warn', 'learn', and 'workflow', which are likely to appear in ordinary conversation. In an instruction-first skill with read/write/exec permissions, this can cause unintended activation and execution of memory-related actions without clear user intent, increasing the risk of accidental data storage, retrieval, or side effects.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The README explicitly instructs users to configure automatic saving and analysis of session content, but it does not provide a clear privacy notice, consent model, retention policy, or warning that potentially sensitive conversation data will be stored and processed. In a memory skill, this omission is materially risky because users may unknowingly persist secrets, personal data, or proprietary information to disk and scheduled jobs may continue processing it unattended.

Ssd 3

Medium
Confidence
94% confidence
Finding
The README openly describes persistent capture of session content and long-term reuse through chronicle and monograph memory features. Persistent storage of conversational data meaningfully increases the blast radius of accidental secret capture, user profiling, and later unintended retrieval, especially when paired with exact timestamps and long-term importance tracking.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The proactive trigger feature is described as reading recent user messages, counting terms, and automatically loading memories, but the documentation does not clearly warn users that their messages are being continuously monitored for behavioral triggers. This creates a surveillance-like behavior that can expose sensitive topics, infer intent, and increase accidental processing of confidential data without informed consent.

Ssd 3

Medium
Confidence
95% confidence
Finding
This feature combines scanning recent user messages with automatic memory activation, which turns passive chat history into a continuously reused behavioral signal. In context, that makes the skill more dangerous because it can surface old sensitive material based on repeated keywords and encourage hidden stateful behavior that the user may not anticipate.

Vague Triggers

Medium
Confidence
95% confidence
Finding
The workflow examples use generic phrases like "deploy" and "send report" as implicit triggers for multi-step actions. In an agent context, broad natural-language triggers can cause unintended execution or expansion of sensitive workflows when those phrases appear in ordinary conversation, especially if the system automatically retrieves and acts on stored procedures.

Vague Triggers

Medium
Confidence
97% confidence
Finding
The proactive triggers are keyed on common, high-frequency words like "database" and "api", causing memory to be loaded automatically whenever those terms appear. That creates a context-injection and privacy risk: irrelevant or sensitive stored memory may be prepended to future prompts without clear user intent, influencing outputs or disclosing prior information.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The documentation states that session content is auto-saved and loaded memory is prepended to future responses, but it does not present this as a prominent warning or informed-consent mechanism. Users may unknowingly persist sensitive data and have it silently reintroduced into later contexts, increasing privacy, confidentiality, and prompt-manipulation risk.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
1. Before each response, hippocampus scans your message
2. If a trigger keyword is found, it loads the associated memory file
3. The loaded memory is prepended to context for this response
4. You get relevant context without asking for it

This is configured via `PROACTIVE_KEYWORDS` in USER_CONFIG.md.
Confidence
94% confidence
Finding
The skill explicitly advertises behavior "without asking," meaning it autonomously scans messages and injects memory into context before responding. In a memory-augmented agent, autonomous hidden context changes are dangerous because they bypass explicit user intent, can expose sensitive prior data, and make prompt behavior easier to manipulate through crafted conversation.

Vague Triggers

Medium
Confidence
93% confidence
Finding
The proactive keyword triggers use common terms like 'project', 'database', 'api', and 'error' to automatically load memory. In a conversational agent, these broad triggers can activate on routine discussion and cause unintended context injection, which may bias responses, surface irrelevant stored data, or expose prior memory content without an explicit user request.

Vague Triggers

Medium
Confidence
91% confidence
Finding
The instant and threshold trigger rules automatically react to frequent everyday words on a 1-minute heartbeat, which increases the chance of accidental or adversarial activation through normal conversation. This creates a prompt-injection-like pathway where a user can deliberately repeat benign terms to force memory loading and influence subsequent agent behavior.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The state loader and related status functions are documented as handling persistent word counts and sliding-window analysis, and `readingbetweenthelines_stat()` reports tracked words from `state['word_counts']`. However, `readingbetweenthelines()` only tokenizes the current `messages` in memory and updates cooldowns; it never writes computed counts back to `state['word_counts']`, so the documented persistent counting behavior does not actually occur.

Session Persistence

Medium
Category
Rogue Agent
Content
def _save_reading_state(state: Dict):
    """Persist state to disk"""
    fpath = _reading_state_path()
    fpath.parent.mkdir(parents=True, exist_ok=True)
    with open(fpath, 'w', encoding='utf-8') as f:
Confidence
88% confidence
Finding
Persisting reading-state data to disk is not inherently unsafe, but in this skill it contributes to cross-session retention of user-derived behavioral/contextual data without strong user controls. Combined with other memory features, this expands the privacy footprint and may retain patterns about user discussions longer than expected.

Session Persistence

Medium
Category
Rogue Agent
Content
def _update_keyword_index(topic: str, keywords: Dict, source_path: Path):
    """Update keyword index files — index_dir already created by _lazy_init()"""
    index_dir = get_index_path()
    # No mkdir needed: _lazy_init() already ran via save_monograph() or save_chronicle()
    
    for kw in list(keywords.keys())[:10]:
        kw_file = index_dir / f"{kw}.md"
Confidence
60% confidence
Finding
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.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The auto-save flow persists conversation/context data to disk without any consent gate, warning, or content minimization. In a memory skill that handles arbitrary user conversation, this creates a realistic privacy and sensitive-data retention risk, especially if secrets, personal data, or internal project details are present in context.

Ssd 3

Medium
Confidence
91% confidence
Finding
The skill is intentionally designed to retain natural-language conversation content and later reuse it, which creates a data retention and secondary disclosure channel. Even without malice, storing free-form context in markdown and SQLite makes accidental leakage of confidential prompts, credentials, or personal information more likely through later recall or file access.

Ssd 3

Medium
Confidence
93% confidence
Finding
The recall path returns previews of previously saved content in response to ordinary queries, which can surface sensitive information that was stored earlier. In this skill's context, memory retrieval is a core feature, so any secret or private data written into Chronicle can later be echoed back with minimal friction.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
`_cmd_autocheck()` can automatically collect recent `content` or `history` and write it to Chronicle/Monograph based on thresholds, again without an explicit warning at the point of save. Because this path may run from hooks/cron and process accumulated session history, it increases the chance of silently retaining sensitive material beyond user expectations.

Session Persistence

Medium
Category
Rogue Agent
Content
- Execute: python3 {skill_path}/scripts/memory.py autocheck

### 2. Daily memory file creation (midnight)
- Name: hippocampus-daily-create
- Schedule: 0 0 * * *
- Execute: create ~/.openclaw/workspace/memory/heartbeat-YYYY-MM-DD-HHMM.md
Confidence
60% confidence
Finding
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.

Autonomous Decision Making

Medium
Category
Excessive Agency
Content
**I will execute as follows:**
1. Detected hippocampus needs hook configuration
2. Explicitly ask user: "Do you consent to configure auto-save hooks?"
3. After user says "yes", auto-execute hook configuration

---
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.

Ssd 3

Medium
Confidence
90% confidence
Finding
The sync-to-memory feature propagates stored user-derived content into a shared `MEMORY.md`, broadening exposure from this skill's private store into a potentially wider agent context. That increases the blast radius of any sensitive content previously captured, because other components or future sessions may read and reuse it.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The sync command docstring and user-facing text say it will gather recent monographs and build a preview summary. But `list_monographs()` returns only `topic`, `user`, `keywords`, `created_at`, and `updated_at`, so `_cmd_sync_memory()` reads `m['content_preview']` from records that do not contain that field, causing the advertised summary behavior to fail.

Static analysis

No suspicious patterns detected.