T09 · Insecure Skill Coding Practices
- Location
src/extraction/extractor.ts:334- Finding
Raw sensitive conversation content is transmitted before visibility classification
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This memory skill is purpose-aligned, but it needs Review because enabling extraction can send raw conversations to LLM providers despite stronger privacy claims, and cross-agent graph recall can expose private memories.
Install only if you want long-term local conversation memory and are comfortable with complete chats being stored on disk. Keep autoExtract off or use a local Ollama model if conversations may contain secrets, medical, financial, or business-sensitive data. Disable cross-agent recall until the private-fact graph traversal issue is fixed, and restrict filesystem permissions on the data directory.
src/extraction/extractor.ts:334Raw sensitive conversation content is transmitted before visibility classification
src/recall/search.ts:379Cross-agent graph traversal can disclose private facts
src/recall/context-builder.ts:89Attacker-controlled memories can become persistent prompt instructions
src/capture/writer.ts:153Sensitive conversation archives are stored without explicitly restrictive permissions
Code or instructions that leak agent conversation context to external services, potentially exposing sensitive user interactions.
## Key Design Principles
1. **Privacy first** — all data local, no external calls except LLM API
2. **Plugin-ready** — proper OpenClaw plugin from day one
3. **Multi-turn aware** — capture conversation arcs, not single exchanges
4. **Temporal intelligence** — track when and how often topics arise
5. **Configurable** — model, thresholds, visibility rules all configurable
6. **Graceful degradation** — if extraction fails, raw capture still works
The spec directs the system to send file contents to an extraction model but does not require explicit disclosure that local memory files may be transmitted to an external model provider. Because the migrated files may contain medical data, credentials, and other highly sensitive personal information, undisclosed external processing creates substantial confidentiality and compliance risk and directly undermines the 'privacy-first' positioning.
The overall design persistently extracts, stores, deduplicates, indexes, and searches user conversation facts, including sensitive personal information and inferred attributes, creating a durable surveillance-style knowledge base. In a memory skill, this is especially dangerous because retention is broad, automated, and intended to accumulate over time, increasing harm from misuse, compromise, or unexpected secondary use.
The spec claims a privacy-first local memory system, yet directs implementers to send conversation content to external LLM providers or CLI-backed services for extraction. This creates a clear privacy and trust-boundary violation: sensitive user conversations may leave the local device despite the product positioning suggesting otherwise.
The extraction prompt explicitly targets sensitive categories such as credentials, medical information, and financial details, yet the spec contains no mandatory warning, consent, or exclusion controls. Processing and classifying such data magnifies privacy harm if transmitted remotely or retained persistently.
The code is consistent with part of the declared purpose: it locally captures and persists conversation data, and all storage shown is local filesystem/SQLite. However, the declared description presents a broader capability set—specifically structured fact extraction via LLM and auto-recall of relevant knowledge before each turn—that is not implemented in this chunk. Additionally, the description says stored data stays local in SQLite, but this code also writes human-readable JSONL backups to the local filesystem, which is an undeclared storage behavior and slightly inconsistent with the SQLite-only wording. The mismatch is therefore best classified as partial: the code matches the capture/local-persistence aspect, but not the extraction/recall aspects, and it uses an additional storage format not reflected in the description.
The declared description is about agent memory functionality: capturing conversations, extracting facts via LLM, and recalling relevant knowledge. This code chunk does none of that. Instead, it implements a standalone CLI for token administration against a local SQLite database. While it does use the same local SQLite datastore path, the primary purpose and capabilities are materially different from the declared memory feature. This is not merely a supporting detail; it is a separate token-management capability that is undeclared in the description.
The declared description emphasizes privacy-first local persistence where all stored data stays local in SQLite. However, this code transmits fact summaries and truncated fact content to Anthropic's API for classification, which is a material undeclared external data-sharing capability and conflicts with the privacy/local-only claim. The code also performs a background relation-sweep job to build typed graph edges among facts, which is adjacent to memory functionality but not clearly represented by the stated description. The strongest mismatch is the external API use despite the description claiming local-only handling.
The description claims a privacy-first system where all stored data stays local in SQLite, which implies strongly local handling of memory data. However, this code explicitly transmits conversation text to external LLM services such as Anthropic, OpenAI, and Mistral, using API keys and remote HTTP requests. That is a material undeclared capability and weakens the 'all local' privacy representation. The code does align with part of the declared purpose—extracting structured facts via LLM for memory—but the implementation is not strictly local and can export conversation content off-device. That makes the description materially misleading relative to actual behavior.
The code is related to the broader memory system, but this specific chunk does not implement the declared primary behavior of capturing conversations and auto-recalling knowledge before each turn. Instead, it performs a separate migration task: it enumerates configured files, reads local memory documents, inserts synthetic conversation rows, invokes extractFacts using externally hosted models (Anthropic/OpenAI/Mistral/etc.), and logs extraction results. This also weakens the 'all stored data stays local' claim as written, because while storage is local SQLite, the content is transmitted to external LLM APIs for extraction. Therefore the description does not accurately represent this code chunk's actual behavior.
The code is broadly related to the declared memory-recall purpose, so the core function matches. However, it includes materially significant capabilities not reflected in the description. Most notably, it retrieves shared facts from other agents ('cross-agent recall'), which expands scope beyond a purely local per-agent memory system and weakens the stated 'all stored data stays local in SQLite' framing unless that sharing model is explicitly disclosed. It also performs knowledge-graph traversal and optional embedding-based semantic retrieval, and calls an OpenClaw runner for LLM-based query planning during search. These are not merely minor implementation details because they affect what data can be accessed and how retrieval operates. The primary purpose is still memory recall, but the undeclared cross-agent access and richer retrieval mechanisms make the description incomplete enough to count as a mismatch.
The code largely matches the declared purpose in that it provides persistent local SQLite storage for conversations and structured facts, with retrieval/search features suitable for memory recall. It does not itself call an LLM or perform automatic pre-turn recall in this chunk, but that omission alone is not necessarily a mismatch because this file is clearly a storage layer. However, there are material undeclared capabilities: the database supports cross-agent shared facts and a 'master knowledge base' that retrieves knowledge from other agents, which goes beyond a strictly local per-agent memory description. Additionally, schema migration comments indicate support for remote JSONL ingest (ingest_tokens and ingest_file_log), which is not mentioned in the description. The privacy claim that all stored data stays local is mostly consistent with this chunk, since it uses local SQLite and does not itself perform network access, but the shared cross-agent memory capability is a meaningful behavioral expansion not reflected in the declared description.
The declared description presents a full agent memory system whose main functions are conversation capture, LLM-based fact extraction, and automatic recall. The supplied code chunk does none of those things. Instead, it is a deduplication sweep utility for an existing local SQLite facts database: it loads fact embeddings, computes pairwise cosine similarity, prints review/merge candidates, and can deactivate lower-priority duplicate facts. While this is related to maintaining a local memory store and remains privacy-preserving/local, its actual purpose is a maintenance operation not represented in the declared description. Therefore this chunk materially differs from the declared behavior.
Most of the schema aligns with the declared purpose: local SQLite persistence for conversations and structured memory, including facts, occurrences, search, and knowledge organization. However, the code also introduces a distinct Phase 3 capability for remote ingest, including authentication tokens and ingest file logging. That is an undeclared capability and goes beyond a purely local-only memory description. While this chunk does not itself implement network handling, the schema clearly supports remote ingestion workflows, which materially conflicts with the privacy-first 'all stored data stays local' framing if undeclared.
Referenced artifact was not completely inspected
npx tsx src/extraction/migrate.ts --all --dry-run
Referenced artifact was not completely inspected
npx tsx src/extraction/migrate.ts --all --dry-run
The top-level description advertises local persistent memory for conversations but does not warn users about retention, privacy implications, or the possibility that sensitive chat content will be stored on disk. Because this plugin's primary purpose is long-term storage, omission of an explicit warning materially increases the risk of users enabling it without understanding the data exposure surface.
The manifest describes cross-agent recall as including shared facts from other agents, but it does not warn that information may flow across agent boundaries. In a memory system, this can cause unintended disclosure of sensitive or context-specific information to other agents that should not have access to it.
The UI help text says the skill will automatically capture all conversation messages, but it does not present an explicit warning about privacy, retention, or sensitive-data storage. Users may enable the feature expecting convenience without realizing that every conversation turn may be persisted and later recalled.
The output schema itself normalizes retention of 'secret' facts, specifically including credentials and sensitive medical or financial details, yet the prompt contains no protective instruction to avoid or quarantine such information. By embedding this into the core extraction contract, the system is likely to capture highly sensitive data whenever it appears in chat.
The prompt directs the system to store secrets and sensitive personal data in structured memory without any visible warning, consent flow, or just-in-time notice to the user. That creates a high risk of silent collection of sensitive data users may reveal conversationally without realizing it will be retained for future recall.
The prompt instructs the model to persist highly sensitive user information into structured memory, including durable personal details and credentials location. This is dangerous because memory systems are designed for later retrieval, so any compromise, prompt abuse, or accidental recall can expose information far beyond the original conversation context.
Defining a dedicated 'secret' category for credentials and sensitive medical or financial details signals intentional long-term retention of the most sensitive classes of user data. In a memory skill, this materially increases the chance of harmful disclosure through local compromise, debugging, sync mistakes, or model-driven resurfacing in unrelated contexts.
The code sends parsed conversation text to extractFacts using a named external model, which means sensitive local session content may be transmitted to a remote LLM service. That behavior conflicts with the skill's privacy-first/local-storage description and can expose personal or confidential conversation data without clear user expectation or informed consent.
The code sends fact summaries and truncated fact content to Anthropic's remote API for relation classification, which directly conflicts with the skill's stated privacy model that all stored data stays local in SQLite. This creates a data exfiltration/privacy risk because locally persisted memory may contain sensitive user or agent information that is transmitted off-device to a third party.
Detected: suspicious.env_credential_access