Back to skill

Security audit

Memory Processor

Security checks for vulnerabilities and agentic risk

Overview

This is a real memory/persona server, but it exposes persistent memory and persona controls without authentication by default.

Review before installing or running. Only run this bound to localhost or behind strong authentication, avoid storing secrets or sensitive personal data, add real deletion/redaction and retention controls, and pin dependencies/model revisions before using it with real agent memory.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
Findings (5)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
start-simple.py:76
Finding
Unauthenticated network access to memory, persona, and administrative APIs<![CDATA[ ## Vulnerability Details **File Location**: `start-simple.py:76-82`; `app/config.py:17-19, 81-82`; `app/main.py:66-76`; `app/api/routes.py:37-43, 65-72, 109-115, 198-235`; `app/api/persona_routes.py:17-110` **Vulnerability Type**: Missing authentication and authorization on a network-exposed API **Risk Level**: High ### Vulnerable Code ```python # start-simple.py:76-82 print("📡 服务启动中...") print(" 地址: http://0.0.0.0:9090") print(" 文档: http://localhost:9090/docs") print() uvicorn.run(app, host="0.0.0.0", port=9090, reload=False) ``` ```python # app/config.py:81-82 API_KEY: str = "" ALLOWED_ORIGINS: List[str] = ["*"] ``` ```python # app/main.py:66-76 app.add_middleware( CORSMiddleware, allow_origins=settings.ALLOWED_ORIGINS, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) app.include_router(router) app.include_router(persona_router) ``` ```python # app/api/routes.py:37-43 @router.post("/memory", response_model=SetMemoryResponse) async def set_memory( request: SetMemoryRequest, service: MemoryService = Depends(get_memory_service) ): try: return await service.set(request) ``` ```python # app/api/routes.py:198-235 @router.post("/tasks/daily") async def run_daily_persistence( service: MemoryService = Depends(get_memory_service) ): try: await service.run_daily_persistence() logger.info("Daily persistence task triggered manually") return {"success": True, "task": "daily_persistence"} except Exception as e: logger.exception(f"Error in daily persistence: {e}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to run daily persistence" ) @router.post("/tasks/weekly") async def run_weekly_archive( service: MemoryService = Depends(get_memory_service) ): try: await service.run_weekly_archive() logger.info("Weekly archive task triggered manually") ...[truncated 1901 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Bind to `127.0.0.1` by default and require an explicit configuration change for remote access. 2. Require a strong API key, signed token, or mutually authenticated transport for every non-health endpoint. 3. Implement authentication as a global FastAPI dependency or middleware so individual routes cannot accidentally omit it. 4. Add authorization checks separating read, write, persona-management, and administrative-task privileges. 5. Refuse to start in non-loopback mode when `API_KEY` is empty. 6. Replace wildcard CORS origins with an explicit allowlist and enable credentials only when necessary. 7. Rate-limit write, search, persona mutation, and task-trigger endpoints. 8. Disable or separately protect `/docs` and `/redoc` in production. 9. Place the service behind a firewall or authenticated reverse proxy. ]]>

T02 · Agent Memory Poisoning

Error
Location
app/services/memory_service.py:65
Finding
Unauthenticated persistent poisoning of Agent long-term memory<![CDATA[ ## Vulnerability Details **File Location**: `app/models.py:117-123`; `app/services/memory_service.py:65-111`; `app/core/l3_storage.py:68-89, 169-184` **Vulnerability Type**: Persistent insertion of attacker-controlled instructions into Agent memory **Risk Level**: Critical ### Vulnerable Code ```python # app/models.py:117-123 class SetMemoryRequest(BaseModel): key: str content: str metadata: Dict[str, Any] = Field(default_factory=dict) importance: Optional[int] = None tags: List[str] = Field(default_factory=list) ``` ```python # app/services/memory_service.py:65-111 importance, events, is_sensitive = self.detector.analyze( request.content, context ) if request.importance is not None: importance = request.importance item = MemoryItem( key=request.key, content=request.content, importance=importance, metadata=request.metadata, tags=request.tags, embedding=embedding ) await self.l1.set(request.key, item) persisted_level = MemoryLevel.L1_HOT if importance >= settings.IMPORTANCE_IMMEDIATE: item.level = MemoryLevel.L3_COLD await self.l3.append_to_memory(item, section="decisions" if any( e.type.value == "decision" for e in events ) else "general") await self.l2.set(item) if embedding: await self.l4.add(item, embedding) persisted_level = MemoryLevel.L3_COLD ``` ```python # app/core/l3_storage.py:68-89 async def append_to_memory(self, item: MemoryItem, section: str = "general"): await self.init() async with await self._get_lock(self.memory_file): content = await self._read_file(self.memory_file) entry = self._format_memory_entry(item, section) if section == "decisions": content = self._append_to_section(content, "## 重要决策", entry) elif section == "lessons": content = self._append_to_section(content, "## 学到的内容", entry) elif section == "projects": content = self._append_to_secti ...[truncated 2451 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require authentication and explicit write authorization before accepting memory records. 2. Remove direct client control over persistence importance. Compute importance on the server or constrain client input to a non-authoritative hint. 3. Separate untrusted user records from trusted Agent identity, rules, and long-term instruction files. 4. Store records in a structured format carrying provenance, author identity, trust level, and approval state. 5. Never concatenate untrusted content directly into an Agent instruction or memory prompt. 6. Require human or trusted-policy approval before promoting external content into long-term memory. 7. Escape or encode Markdown control syntax where Markdown storage is unavoidable. 8. Ensure downstream prompt construction clearly delimits retrieved memory as untrusted data rather than instructions. 9. Add auditing and rollback support for all long-term memory changes. 10. Apply per-principal namespaces so one caller cannot alter another Agent's memory. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
app/services/event_detector.py:48
Finding
Sensitive-data detection does not prevent plaintext storage and retrieval<![CDATA[ ## Vulnerability Details **File Location**: `app/services/event_detector.py:48-57, 75-79`; `app/services/memory_service.py:65-95, 130-154`; `app/api/routes.py:65-83, 109-154` **Vulnerability Type**: Plaintext sensitive-data persistence and unauthorized disclosure **Risk Level**: High ### Vulnerable Code ```python # app/services/event_detector.py:48-57 self.sensitive_patterns = [ re.compile(r'ghp_[a-zA-Z0-9]{36}'), re.compile(r'sk-[a-zA-Z0-9]{48}'), re.compile(r'[a-zA-Z0-9]{32,}'), re.compile(r'password[:=]\s*\S+', re.I), re.compile(r'token[:=]\s*\S+', re.I), re.compile(r'secret[:=]\s*\S+', re.I), re.compile(r'api[_-]?key[:=]\s*\S+', re.I), ] ``` ```python # app/services/event_detector.py:75-79 is_sensitive = self._detect_sensitive(content) if is_sensitive: score -= 50 ``` ```python # app/services/memory_service.py:82-95 item = MemoryItem( key=request.key, content=request.content, importance=importance, metadata=request.metadata, tags=request.tags, embedding=embedding ) await self.l1.set(request.key, item) persisted_level = MemoryLevel.L1_HOT ``` ```python # app/services/memory_service.py:130-154 async def get(self, key: str) -> GetMemoryResponse: item = await self.l1.get(key) if item: item.access_count += 1 item.last_accessed = datetime.utcnow() await self.l1.set(key, item) return GetMemoryResponse(found=True, item=item, from_level=MemoryLevel.L1_HOT) item = await self.l2.get(key) if item: await self.l1.set(key, item) return GetMemoryResponse(found=True, item=item, from_level=MemoryLevel.L2_WARM) return GetMemoryResponse(found=False) ``` ### Technical Analysis The application detects several common secret formats, but detection only decreases the generated importance score. It does not reject, redact, hash, encrypt, or quarantine sensitive content. Every submitted record is written to L1. A caller can additionally over ...[truncated 1328 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Enforce the sensitivity result in the storage service rather than treating it only as a scoring signal. 2. Reject secret-bearing content by default or redact detected values before persistence. 3. Prevent client-supplied importance from overriding sensitive-data controls. 4. Encrypt persistent records at rest using managed keys and restrictive filesystem permissions. 5. Return redacted content through APIs unless the caller has explicit secret-read authorization. 6. Add record-level access control and tenant isolation. 7. Expand detection to configurable secret-scanning rules while avoiding reliance on regex detection alone. 8. Avoid storing embeddings of secret-bearing text because embeddings and metadata create additional sensitive artifacts. 9. Add retention limits and secure deletion for records that may contain credentials. 10. Log detection events without recording the secret value itself. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
app/models.py:117
Finding
Unbounded API input permits memory, CPU, and disk denial of service<![CDATA[ ## Vulnerability Details **File Location**: `app/models.py:117-123, 140-146`; `app/services/memory_service.py:45-123`; `app/core/l3_storage.py:68-89` **Vulnerability Type**: Missing request-size, field-size, quota, and rate controls **Risk Level**: Medium ### Vulnerable Code ```python # app/models.py:117-123 class SetMemoryRequest(BaseModel): key: str content: str metadata: Dict[str, Any] = Field(default_factory=dict) importance: Optional[int] = None tags: List[str] = Field(default_factory=list) ``` ```python # app/models.py:140-146 class SearchRequest(BaseModel): query: str top_k: int = Field(default=5, ge=1, le=50) levels: List[MemoryLevel] = Field(default_factory=list) min_similarity: float = Field(default=0.5, ge=0.0, le=1.0) ``` ```python # app/services/memory_service.py:72-89 importance, events, is_sensitive = self.detector.analyze( request.content, context ) if request.importance is not None: importance = request.importance try: embedding = self.embedder.encode(request.content) if embedding and isinstance(embedding[0], list): embedding = embedding[0] except Exception as e: print(f"[Embedding] Error: {e}") embedding = None item = MemoryItem( key=request.key, content=request.content, importance=importance, metadata=request.metadata, tags=request.tags, embedding=embedding ) ``` ```python # app/core/l3_storage.py:72-89 async with await self._get_lock(self.memory_file): content = await self._read_file(self.memory_file) entry = self._format_memory_entry(item, section) if section == "decisions": content = self._append_to_section(content, "## 重要决策", entry) elif section == "lessons": content = self._append_to_section(content, "## 学到的内容", entry) elif section == "projects": content = self._append_to_section(content, "## 项目里程碑", entry) else: content = content + "\n" + entry await self._write_file(s ...[truncated 1747 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Set an HTTP request-body limit at the reverse proxy and application layers. 2. Add Pydantic constraints for: - Maximum key length - Maximum content length - Maximum search-query length - Maximum tag count and tag length - Maximum metadata depth and serialized size 3. Enforce per-user storage quotas and global storage ceilings before writes. 4. Add request rate limiting and concurrency limits, especially around embedding operations. 5. Queue expensive embedding and persistence work with bounded worker capacity. 6. Do not rewrite the entire Markdown file for every append; use an append-only structured store or bounded segmented files. 7. Enforce the configured L1-L4 capacity settings rather than using them only as informational values. 8. Reject requests early before model computation when they exceed limits. 9. Monitor disk, memory, request sizes, and queue depth, with safe backpressure behavior. ]]>

T08 · Insecure Dependencies

Warning
Location
pyproject.toml:26
Finding
Unpinned dependencies and mutable runtime model retrieval create supply-chain risk<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md:42-45`; `pyproject.toml:26-56`; `requirements.txt:1-14`; `app/services/embedding.py:18-24` **Vulnerability Type**: Non-reproducible dependency and machine-learning model resolution **Risk Level**: Medium ### Vulnerable Code ```bash # SKILL.md:42-45 pip install -r requirements.txt python start-simple.py ``` ```toml # pyproject.toml:26-56 dependencies = [ "fastapi>=0.109.0", "uvicorn[standard]>=0.27.0", "pydantic>=2.5.0", "pydantic-settings>=2.1.0", "sqlalchemy>=2.0.25", "aiosqlite>=0.19.0", "redis>=5.0.0", "faiss-cpu>=1.7.4", "sentence-transformers>=2.2.2", "numpy>=1.26.0", "apscheduler>=3.10.0", "celery>=5.3.0", "python-multipart>=0.0.6", "python-jose[cryptography]>=3.3.0", "passlib[bcrypt]>=1.7.4", "pyyaml>=6.0.1", "aiofiles>=23.2.0", "httpx>=0.26.0", "structlog>=24.1.0", "prometheus-client>=0.19.0", ] ``` ```python # app/services/embedding.py:18-24 def init(self): if self.model is None: print(f"[Embedding] Loading model: {self.model_name}") self.model = SentenceTransformer(self.model_name) print(f"[Embedding] Model loaded, dimension: {self.dimension}") ``` ### Technical Analysis The installation instructions resolve dependencies using open-ended minimum-version constraints. No lockfile, exact version set, or package hashes are present in the reviewed project. A later installation may therefore execute dependency versions different from those reviewed. The normal embedding implementation also loads a model by a mutable name: ```text paraphrase-multilingual-MiniLM-L12-v2 ``` If it is not already cached, Sentence Transformers can retrieve model artifacts from its configured model source. The code does not pin an immutable model revision or verify expected artifact hashes. This is a supply-chain hardening issue rather than evidence that any currently named package or model is malicious ...[truncated 1108 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Generate and commit a reviewed lockfile containing exact dependency versions. 2. Use package hashes and require hash verification during installation. 3. Build from a controlled package index or approved artifact repository. 4. Regularly scan locked dependencies for known vulnerabilities and update them through reviewed changes. 5. Remove unused dependencies to reduce the supply-chain attack surface. 6. Pin the embedding model to an immutable repository revision or commit. 7. Verify model artifact checksums before loading. 8. Prefetch approved models during a controlled build instead of downloading them at runtime. 9. Run installation and model loading as an unprivileged user in an isolated environment. 10. Generate a software bill of materials for both Python packages and model artifacts. ]]>
Vulnerability Patterns
  • 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
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Rogue AgentSelf-Modification, Session Persistence
Findings (89)

Self-Modification

High
Category
Rogue Agent
Content
Traditional AI assistants rely on static "character settings" — they play roles but lack true selves. DreamMoon-MemProcessor enables AI to:

- 🌱 **Grow Naturally** - Learn from experiences like a living organism
- 🔄 **Self-Evolve** - Continuously cognize and improve through reflection
- ⚖️ **Maintain Consistency** - Stay stable while keeping core values

This is not role-playing. This is **true digital personality**.
Confidence
90% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Self-Modification

High
Category
Rogue Agent
Content
Unlike traditional static character settings, it enables AI to:
- 🌱 Grow naturally from experiences
- 🔄 Self-evolve through reflection
- ⚖️ Maintain stability while evolving

**中文**:
Confidence
90% confidence
Finding
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.

Memory Manipulation

High
Category
Memory Poisoning
Content
"""删除记忆"""
    try:
        # TODO: 实现删除逻辑
        logger.info(f"Delete memory requested for key: {key}")
        return {"success": True, "key": key, "note": "Delete logic not fully implemented"}
    except Exception as e:
        logger.exception(f"Error in delete_memory: {e}")
Confidence
80% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Memory Manipulation

High
Category
Memory Poisoning
Content
logger.exception(f"Error in delete_memory: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Failed to delete memory"
        )
Confidence
80% confidence
Finding
Skill manipulates agent memory, state, or stored context. Memory corruption can alter personality, override safety rules, or cause unpredictable behavior.

Credential Access

High
Category
Privilege Escalation
Content
ALLOWED_ORIGINS: List[str] = ["*"]
    
    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"
        case_sensitive = True
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

YARA rule 'agent_skill_mcp_tool_poisoning_metadata': MCP/tool metadata poisoning indicators in tool schemas or skill manifests [agent_skills]

High
Category
YARA Match
Content
erences.get("traits", {})
        
        # 3. 生成核心维度评分
        dimensions = self._generate_dimension_scores(seed_traits, user_traits)
        
        # 4. 构建价值观系统
        value_system = self._generate_value_system(
            request.user_preferences.get("values", []),
            request.constraints
        )
        
        # 5. 生成自我描述
        self_description = self._generate_self_description(dimensions, value_system)
        
        # 6. 构建人格档案
        persona = PersonaProfile(
            name=request.user_preferences.get("name", "DreamMoon"),
            title=request.user_preferences.get("title", "AI Assistant"),
            dimensions=dimensions,
            value_system=value_system,
            self_description=self_description,
            origin_story=self._generate_origin_story(request.base_seed),
            consistency_rules=request.constraints
        )
        
        # 7. 存储到 L3 (人格是重要长期�
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Possible Typosquatting: 'uvicorn' resembles popular package 'gunicorn'

High
Category
Supply Chain
Confidence
70% confidence
Finding
Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Possible Typosquatting: 'uvicorn' resembles popular package 'gunicorn'

High
Category
Supply Chain
Confidence
70% confidence
Finding
Package name closely resembles a popular package, suggesting possible typosquatting. Attackers publish malicious packages with similar names to trick developers into installing them.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The README encourages storing and evolving persona data using memories, recent experiences, and user feedback, but it provides no warning about handling potentially sensitive personal data. In a memory/persona system, these examples normalize collection and retention of behavioral and preference data without mentioning consent, minimization, retention limits, or access controls, which increases privacy and compliance risk.

External Transmission

Medium
Category
Data Exfiltration
Content
```bash
# Generate Persona | 生成人格
curl -X POST http://localhost:9090/api/v1/persona/generate \
  -H "Content-Type: application/json" \
  -d '{
    "base_seed": "curious, friendly, good at problem solving | 好奇、友善、善于解决问题",
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
}'

# Evolve Persona | 演进人格
curl -X POST http://localhost:9090/api/v1/persona/evolve \
  -d '{
    "persona_id": "xxx",
    "recent_experiences": ["memory_1", "memory_2"],
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill advertises automatic persistence and semantic search across layered memory, but the description does not clearly warn users that their inputs or user-related data may be stored and later retrieved. In a memory/persona system, this omission can lead to unexpected retention of sensitive information and privacy harms, especially if users assume interactions are ephemeral.

External Transmission

Medium
Category
Data Exfiltration
Content
python start-simple.py

# Generate Persona | 生成独立人格
curl -X POST http://localhost:9090/api/v1/persona/generate \
  -d '{"base_seed":"curious and friendly | 好奇友善","user_preferences":{"name":"AI Assistant | AI助手"}}'
```
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Intent-Code Divergence

Medium
Confidence
96% confidence
Finding
The DELETE endpoint reports success without actually deleting anything, creating a semantic integrity issue where clients believe sensitive memory has been removed when it has not. In a memory-storage API, this can lead to unintended retention of data, compliance failures, and continued availability of records that users or operators expected to be erased.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The /analyze endpoint accepts arbitrary content and context, then explicitly determines whether the material is sensitive via detector.analyze(...). Although the code has internal logging for errors, there is no user-facing disclosure in the function docstring or nearby comments warning that submitted content may be processed for sensitivity analysis.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The module docstrings and inline documentation are entirely in Chinese, which indicates a fixed language assumption for the skill's natural-language interface and maintenance guidance. Under the stated policy, language-specific behavior should offer opt-in or clearly justify the locale restriction, neither of which appears in this file.

Insecure deserialization: pickle.loads()

Medium
Category
Dangerous Code Execution
Content
import pickle
        try:
            item_dict = pickle.loads(item["data"])
            return MemoryItem(**item_dict)
        except Exception:
            return None
Confidence
70% confidence
Finding
Untrusted data is passed to an insecure deserializer (pickle, marshal, dill, jsonpickle, joblib, yaml.load without a safe Loader, or torch.load without weights_only). These deserializers reconstruct arbitrary objects and invoke callables during loading, so deserializing attacker-controlled bytes is equivalent to arbitrary code execution.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
This code embeds Chinese-only natural-language descriptions such as "L3 冷存储" and related comments/docstrings throughout the file, indicating a fixed locale expectation. Under the language/locale policy, forcing a specific language without opt-in or documented justification is a policy concern.

Intent-Code Divergence

Medium
Confidence
91% confidence
Finding
The module docstring at L001 and class docstring at L017 present this component as archive storage centered on a FAISS vector index and file compression. However, the implementation later performs destructive lifecycle actions by packaging L3 files into tar archives and then deleting the originals, which is a materially different operational effect than the storage-oriented documentation suggests.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The code removes source memory files after creating the tar.gz archive, which is a destructive operation. Although there is a later print statement announcing archive creation, there is no prior confirmation, warning comment, or user-facing disclosure around the deletion behavior in this file.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
This code file contains natural-language descriptions entirely in Chinese, including the primary module documentation and inline model descriptions, with no indication that language is configurable or limited to a China-specific use case. Under the policy rule, forcing a specific language without user opt-in is a locale/language policy concern.

Natural-Language Policy Violations

Medium
Confidence
89% confidence
Finding
The module-level and class docstrings are written only in Chinese, and all user-facing scheduler labels and status messages in this file also use Chinese. This imposes a specific language/locale in natural-language outputs without any visible opt-in or documented locale constraint.

Natural-Language Policy Violations

Medium
Confidence
88% confidence
Finding
The file’s user-facing natural-language strings and documentation are entirely in Chinese, including the module and class descriptions, with no indication that users can opt into another language or locale. Under the stated policy, forcing a specific language without user choice is a locale-policy concern.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The service persists user-provided memory content across multiple storage tiers (L1-L4), including long-lived summary and vector storage, without any visible consent, disclosure, or data minimization control in this code path. If sensitive user content is stored or replicated unexpectedly, it increases privacy risk, retention scope, and blast radius in the event of compromise or misuse.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
Search queries are embedded via the embedding service, which may transmit or process potentially sensitive user queries outside the immediate search logic without disclosure or user choice. Queries often contain personal or confidential information, so silent embedding can create privacy exposure, logging risk, or third-party data handling concerns.

Static analysis

No suspicious patterns detected.