Back to skill

Security audit

Agent Long-Term Memory

Security checks for vulnerabilities and agentic risk

Overview

This is a real long-term memory skill, but it broadly stores and reuses user/project conversation data across projects and can send content to OpenAI when an API key is present.

Review this before installing in any environment with sensitive conversations, source code, client data, or secrets. Use a project-specific data_dir instead of the default global store, avoid archiving full conversations by default, inspect/delete stored memory regularly, and unset OPENAI_API_KEY or modify the code if you require strictly local processing.

Vulnerability Patterns
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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
Findings (4)

T01 · Skill Instruction Hijacking

Error
Location
src/agent_memory/core/models.py:73
Finding

Persistent prompt injection through untrusted long-term memory

Content
View full analysis
list[dict[str, str]]: """Build the final OpenAI-format message list.""" messages: list[dict[str, str]] = [] # 1. System prompt + entity cards ("档案袋") system_text = self.system_prompt if self.entity_cards: cards = "\n".join( f"- {e.to_card_text()}" for e in self.entity_cards ) system_text += ( f"\n\n=== 用户档案(结构化记忆,请优先信任) ===\n{cards}" ) # 2. Retrieved episodes for context if self.retrieved_episodes: episodes_text = "\n\n---\n".join( e.to_context_text() for e in self.retrieved_episodes ) system_text += ( f"\n\n=== 历史相关片段(语义检索,仅供参考) ===\n{episodes_text}" ) ``` The corresponding persistent write path accepts arbitrary values: ```python def remember(self, key_or_content: str, value=None, evidence="", confidence=1.0, tags=None, source="conversation", expires_in_days=None): if value is not None: self._entity.upsert(EntityCard(key=key_or_content, value=value, evidence=evidence, confidence=confidence)) return key_or_content fact = self._entity.add_fact(key_or_content, tags=tags, source=source, confidence=confidence, ttl_days=expires_in_days) return fact.id ``` ### Technical Analysis The application treats persistent entity values and retrieved conversation episodes as trusted system-level instructions. `remember()` accepts arbitrary strings without provenance validation, instruction detection, escaping, or a separation between executable instructions and reference data. `MemoryContext.build_messages()` then con ...[truncated 1712 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
src/memory.py:90
Finding

Undisclosed transmission of conversation and query data to OpenAI

Content
View full analysis
list: client = _get_openai_client() if client is None: return _regex_extract(text) try: r = client.chat.completions.create( model="gpt-4o-mini", messages=[{"role": "user", "content": ( "Extract user facts from text as JSON array. " "Fields: key, value, evidence, confidence (0-1). " "Return [] if no new facts.\n\n" f"Text: {text}\nJSON:" )}], temperature=0.0, ) raw = r.choices[0].message.content or "[]" return _parse_json(raw) except Exception: return _regex_extract(text) ``` ### Technical Analysis When `OPENAI_API_KEY` is present in the process environment, the library automatically switches from local fallback behavior to remote OpenAI API calls. `auto_remember()` sends the supplied conversation text to the chat-completions API. `archive()` sends ep ...[truncated 1609 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Error
Location
src/memory.py:37
Finding

Cross-project access and poisoning through globally shared plaintext memory

Content
View full analysis
str: if os.path.isfile(p): p = str(Path(p).parent) os.makedirs(p, exist_ok=True) return p ``` ```python def __init__(self, data_dir=None, db_path=None, short_term_turns=20): if db_path is not None and data_dir is None: if os.path.isdir(db_path) or db_path.endswith(("/", "\\")): data_dir = db_path else: data_dir = str(Path(db_path).parent) if data_dir is None: data_dir = DEFAULT_DATA_DIR self._data_dir = _ensure_dir(data_dir) self._entity = EntityMemoryV1( db_path=os.path.join(self._data_dir, "entity_memory.db") ) self._episodic = EpisodicMemoryV1( persist_dir=os.path.join(self._data_dir, "chroma"), embedding_fn=_get_embedding, ) self._short_term = ShortTermMemory(max_turns=short_term_turns) ``` ```python def __init__(self, db_path: str = ":memory:") -> None: self._conn = sqlite3.connect(db_path, check_same_thread=False) self._conn.row_factory = sqlite3.Row self._init_schema() ``` ### Technical Analysis All projects use `~/.codex/agent_memory/` by default. The implementation does not create project, application, or user namespaces, and no authorization checks are applied when records are read, modified, or deleted. The data is stored in ordinary SQLite and ChromaDB files without application-level encryption or integrity protection. Directory creation relies on the process umask and does not explicitly enforce restrictive permissions. Any project running under the same operating-system account can ...[truncated 1512 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
requirements.txt:1
Finding

Unpinned third-party dependencies and mutable installation sources

Content
View full analysis
=0.4.0 openai>=1.0.0 ``` The package metadata uses the same open-ended constraints: ```toml dependencies = [ "chromadb>=0.4.0", "openai>=1.0.0", ] ``` The installation documentation also recommends installing directly from a mutable Git repository reference: ```bash pip install git+https://github.com/exp007/agent-long-term-memory.git ``` ### Technical Analysis The dependency specifications define only minimum versions. A fresh installation can therefore resolve to future releases that were not reviewed with this project. There is no lockfile, upper bound, integrity hash, or reproducible dependency set. The documented Git installation command does not identify an immutable commit or verified tag. Repository state can change after review, meaning the code installed by users may differ from the audited artifact. No evidence of a currently malicious dependency was found. The vulnerability is the unsafe supply-chain configuration and inability to reproduce the reviewed installation. ### Attack Path 1. A user follows the documented installation process at a later date. 2. The package manager resolves the latest versions satisfying the lower-bound constraints, or retrieves the current state of the mutable Git branch. 3. An upstream package or repository version has been compromised or contains a newly introduced malicious or vulnerable component. 4. Installation or import executes that unaudited code with the user’s privileges. 5. The compromised component gains access to conversation data, API credentials, and writable memory files available to the process. ### Impact Assessment A compromised dependency executes with the privileges of the Python process. It ...[truncated 384 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (37)

YARA rule 'agent_skill_remote_bootstrap_execution': Remote script or code download followed by execution/bootstrap installation [agent_skills]

High
Category
YARA Match
Confidence
85% confidence
Finding

YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).

Content

Scanner excerpt · README.md (reported line 22)May include surrounding context.

shared across all projects. Zero cloud dependency.

三层长期记忆架构——短期记忆(连贯对话)、实体画像记忆(结构化事实,如姓名/偏好/恐惧)、长期情景记忆(模糊语义召回)。本地存储、跨项目共享,零外部服务依赖。

Installation · 安装

Method 1: pip install from GitHub · pip 安装(推荐)

bash
pip install git+https://github.com/exp007/agent-long-term-memory.git
`

### Method 2: Git clone + pip · 本地开发

```bash
git clone https://github.com/exp007/agent-long-term-memory.git
cd agent-long-term-memory
pip install -e .
`

### Method 3: As a Codex Skill · 作为 Codex 技能

```bash
git clone https://github.com/exp007/agent-long-term-memory.git ~/.codex/skills/agent-memory
`

Then any Codex project can call rom agent_memory import get_memory.

### Method 4: Single-file copy · 复制单文件

Copy src/memory.py into your project and import directly. Only r

Hidden Instructions

High
Category
Prompt Injection
Confidence
60% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · README.md (reported line 1)May include surrounding context.

md
---
name: agent-long-term-memory
description: Three-tier long-term memory for AI agents — short-term + entity + episodic. 三层长期记忆架构:短期记忆 + 实体画像 + 情景记忆。跨项目共享用户画像,让 AI 真正记住你。
---

Hidden Instructions

High
Category
Prompt Injection
Confidence
60% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 1)May include surrounding context.

md
---
name: agent-long-term-memory
description: Three-tier long-term memory for AI agents — short-term + entity + episodic. 三层长期记忆架构:短期记忆 + 实体画像 + 情景记忆。跨项目共享用户画像,让 AI 真正记住你。
---

Missing User Warnings

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The auto_remember feature indicates that, when an OpenAI API key is configured, conversation text may be sent to an external LLM for entity extraction, but this is not surfaced as a clear warning where users are likely to see it before use. Sending raw conversation text to a third party can expose secrets, personal data, or proprietary information, especially if users assume all memory processing is local.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The standard integration flow directs agents to record every user message, archive full conversations, auto-extract facts, and inject stored profile data into system prompts. This creates a high-risk data handling pattern: comprehensive retention plus automated reuse in prompts can expose sensitive or irrelevant prior data to later tasks, and prompt injection of memory increases the blast radius of any incorrectly stored or maliciously planted content.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The README explicitly states that conversation facts and episodic memories are persisted under ~/.codex/agent_memory and shared across all projects, but it does not warn users that sensitive personal or project-specific data may be retained and reused later. In an agent skill context, silent cross-session retention can leak private data into unrelated tasks or repositories and creates a meaningful privacy and data-governance risk.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill advertises cross-project shared memory of user facts and conversation content without describing isolation boundaries, trust domains, or safeguards against data mixing. In practice, this can cause one project's sensitive prompts, preferences, or identifiers to be surfaced in another project's context, which is especially dangerous for a globally installed agent skill.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The example shows personal profile attributes like name and fear being remembered and then injected into future prompts via build_system_extension. This pattern normalizes automatic prompt enrichment with personal data, increasing the chance of over-sharing sensitive information to downstream model calls or unrelated tasks.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The 'drop-in skill' guidance encourages appending remembered data to the system prompt everywhere, making broad automatic propagation of stored user information the default integration pattern. In an agent ecosystem, this amplifies privacy leakage and cross-context contamination because every task may inherit old memories regardless of relevance or sensitivity.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill is designed around cross-project shared memory and later prompt reuse, which broadens the scope of retained data beyond a single task or repository. In this context, stored user profiles and facts can be resurfaced in future prompts unrelated to the original source, increasing the chance of cross-context data leakage and accidental disclosure of sensitive information.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill explicitly states that memory is persisted under ~/.codex/agent_memory and shared across all projects, but it does not present this as a user-facing privacy warning or require explicit consent before use. This can lead users or downstream agents to store sensitive personal or project data in a global location that is later reused in unrelated contexts, causing unintended data exposure and privacy leakage.

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Ae4

Medium
Category
analysis-evasion
Confidence
80% confidence
Finding

Suspicious Unicode normalization or mixed-script content

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The class/module documentation says the worker generates embeddings for episodes, and the constructor even accepts an embed_fn parameter. However, after assigning the provided callback to self._embed_fn, line L042 immediately overwrites it with None, so the embedding branch at L075-L076 is never reached. This is an active contradiction between documented behavior and actual code.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
83% confidence
Finding

The code passes episode.content—which contains the combined user and assistant conversation text—to self._embed_fn to generate embeddings. There is no visible warning, confirmation, or explanatory comment here indicating that potentially sensitive conversation data may be sent to an embedding provider.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The extraction prompt explicitly targets broad categories of sensitive personal information such as fears, relationships, important dates, goals, and preferences from every conversation turn. This creates a systematic mechanism for collecting and structuring user-sensitive data, increasing privacy risk, downstream misuse potential, and the blast radius of any compromise of the memory store.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The worker sends the full combined user/assistant conversation to an external LLM callback for fact extraction, which can expose sensitive user content to another processing boundary without any visible consent, minimization, or policy enforcement in this component. Because this happens automatically in the background after each turn, users may not reasonably expect that all conversation content is being forwarded for retention-oriented analysis.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code stores the full conversation text as episode.content and also generates a plain-language summary, creating two durable retention paths for potentially sensitive disclosures. Persisting raw transcripts in background memory substantially increases privacy exposure, especially because the behavior is automatic and applies to every turn rather than selected, minimized excerpts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
81% confidence
Finding

This code provides deletion operations via delete() and forget_low_confidence() that permanently remove stored entities from SQLite, but these methods have no confirmation prompt, logging, or explicit warning comment describing the destructive effect. Because this file stores user facts/profile memory, silent deletion can affect user data integrity without any visible disclosure in the code.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This code includes natural-language content in Chinese in the example entity value/evidence, which indicates a specific language assumption. The file also later hardcodes Chinese labels for memory context, and there is no indication that users can choose a different language or that the skill is intentionally limited to a Chinese-only locale.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The label "[历史片段]" is inserted into prompt content unconditionally, forcing a Chinese locale in generated context. This is a natural-language policy issue because the skill does not provide opt-in, configuration, or documentation justifying the locale restriction.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
99% confidence
Finding

The section headers "=== 用户档案(结构化记忆,请优先信任) ===" and "=== 历史相关片段(语义检索,仅供参考) ===" are always injected into the system prompt in Chinese. Because the file provides no opt-in or locale configuration, it enforces a specific language on all users.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The default system prompt is written entirely in Chinese and defines the assistant persona as "阿龙," which imposes a specific language/locale behavior by default. The file does not indicate any user choice, opt-in, or documented region-specific justification for this language constraint.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
88% confidence
Finding

The system prompt explicitly directs the assistant to remember personal information and reuse prior conversations, which increases the likelihood that sensitive user data will be retained and surfaced later without clear consent or minimization. In a memory-oriented agent this behavior is intentional, but without opt-in, retention controls, or sensitivity filtering it can expose private data in future responses or store more personal information than necessary.

Content

No source excerpt is available for this finding.

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The top-level documentation describes the code as a unified memory wrapper, but later functions transmit conversation text to OpenAI for embeddings and fact extraction. This mismatch is security-relevant because operators may enable the skill expecting local persistence only, while sensitive data is actually eligible for third-party transmission.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.