Back to skill

Security audit

long-term-task-memory

Security checks for vulnerabilities and agentic risk

Overview

This skill is a coherent Milvus-based long-term memory tool, but it needs Review because its current implementation can expose or corrupt stored memories through weak transport and unsafe query construction.

Install only if you are comfortable storing selected memories in your Milvus service. Use a dedicated low-privilege Milvus account, prefer TLS/HTTPS endpoints, avoid putting secrets or confidential data into memory records, and treat delete, update, and --recreate operations carefully until the filter escaping and confirmation safeguards are fixed.

Vulnerability Patterns
  • 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
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/milvus_manager.py:276
Finding
Milvus Filter Expression Injection Through Unescaped CLI Arguments## Vulnerability Details **File Location**: `scripts/milvus_manager.py:276-287`, `scripts/milvus_manager.py:335`, `scripts/milvus_manager.py:393`, and `scripts/milvus_manager.py:442` **Vulnerability Type**: Milvus filter-expression injection **Risk Level**: High ### Vulnerable Code ```python # Build filter expression filters = [] if category: filters.append(f'category == "{category}"') if role: filters.append(f'role == "{role}"') if project: filters.append(f'project == "{project}"') if event: filters.append(f'event == "{event}"') if status: filters.append(f'status == "{status}"') if priority: filters.append(f'priority == "{priority}"') filter_expr = " and ".join(filters) if filters else None ``` The same unsafe construction is used when retrieving a record: ```python results = self.client.query( collection_name=self.collection_name, filter=f'memory_id == "{memory_id}"', output_fields=["*"] ) ``` It is also used in the update path: ```python self.client.delete( collection_name=self.collection_name, filter=f'memory_id == "{memory_id}"' ) ``` And in the deletion path: ```python self.client.delete( collection_name=self.collection_name, filter=f'memory_id == "{memory_id}"' ) ``` ### Technical Analysis Values received from the command-line options `--category`, `--role`, `--project`, `--event`, `--status`, `--priority`, and `--memory-id` are interpolated directly into Milvus filter expressions. The implementation neither escapes string-literal metacharacters nor validates these values against strict formats or allowlists. If an attacker can influence an argument, a value containing a closing quotation mark and valid Milvus expression syntax can alter the predicate rather than being treated as literal data. The exact payload syntax depends on the expression grammar supported by the deployed Milvus version, but the v ...[truncated 1690 chars]
Remediation
## Remediation Suggestions 1. Validate `memory_id` as a UUID before constructing any query: ```python def validate_memory_id(value: str) -> str: parsed = uuid.UUID(value, version=4) if str(parsed) != value.lower(): raise ValueError("Invalid memory ID") return str(parsed) ``` 2. Restrict enum-like fields such as `category`, `status`, and `priority` to explicit allowlists. 3. Apply strict length and character policies to free-form dimensions such as `role`, `project`, and `event`. If these fields must accept broad Unicode text, use a dedicated Milvus string-literal escaping function rather than a restrictive character allowlist. 4. Prefer a parameterized or structured filter API if supported by the deployed `pymilvus` version. Do not concatenate untrusted values into expression-language strings. 5. If raw filter construction is unavoidable, implement and test escaping for quotation marks, backslashes, control characters, and all other Milvus string-literal metacharacters. 6. Use a minimally privileged Milvus account restricted to the required database and collection. 7. Add tests that submit quotation marks and expression operators through every filter argument and verify that they are handled only as literal values.

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:35
Finding
Milvus Credentials and Long-Term Memory May Be Transmitted Over Plaintext HTTP## Vulnerability Details **File Location**: `SKILL.md:35-38` and `scripts/milvus_manager.py:100-119` **Vulnerability Type**: Missing enforcement of encrypted transport for credentials and sensitive records **Risk Level**: High ### Vulnerable Code and Configuration The documented configuration explicitly demonstrates a plaintext HTTP endpoint: ```bash # Milvus instance endpoint MILVUS_URI=http://your-instance.milvus.ivolces.com:19530 # Milvus authentication token (format: Username:Password) MILVUS_TOKEN=root:yourpassword ``` The implementation accepts the URI without validating its scheme or requiring transport encryption: ```python # Get URI and token from environment variables uri = os.getenv("MILVUS_URI") token = os.getenv("MILVUS_TOKEN") # Check configuration completeness missing_configs = [] if not uri: missing_configs.append("MILVUS_URI(实例访问地址,格式:http://your-instance.milvus.ivolces.com:19530)") if not token: missing_configs.append("MILVUS_TOKEN(认证令牌,格式:Username:Password,如 root:yourpassword)") if missing_configs: error_msg = "❌ 缺少必要的配置项,请在 .env 文件中设置以下值:\n" for config in missing_configs: error_msg += f" - {config}\n" error_msg += "\n.env 文件位置:scripts/.env 或当前工作目录下的 .env" raise ValueError(error_msg) # Connect using MilvusClient self.client = MilvusClient(uri=uri, token=token) ``` ### Technical Analysis The Skill handles a username-and-password token and potentially sensitive long-term-memory content. Its documentation instructs users to configure an `http://` endpoint, while the code accepts that endpoint without requiring TLS. When the configured Milvus deployment and client communicate over plaintext transport, authentication information and database operations lack network-layer confidentiality and server authentication. This can expose both the credential token and memory records to an attacker with a suitable network position. The finding d ...[truncated 1608 chars]
Remediation
## Remediation Suggestions 1. Replace all documented remote `http://` examples with authenticated, encrypted `https://` or the appropriate TLS-enabled Milvus transport. 2. Parse and validate `MILVUS_URI` before connecting. Reject plaintext remote schemes by default: ```python from urllib.parse import urlparse parsed = urlparse(uri) if parsed.scheme != "https": raise ValueError("MILVUS_URI must use an encrypted HTTPS endpoint") ``` 3. If plaintext transport is required for local development, require an explicit opt-in and restrict it to loopback hosts such as `127.0.0.1`, `::1`, or `localhost`. 4. Configure certificate verification and a trusted certificate authority. Do not disable hostname or certificate validation. 5. Use a dedicated, minimally privileged Milvus account limited to the required collection and operations. 6. Rotate credentials after migrating any existing plaintext deployment to TLS, because previously transmitted credentials may already have been exposed. 7. Avoid password reuse and use a secret manager or protected environment injection instead of persistent plaintext `.env` files where the deployment platform supports it. 8. Add automated tests that reject insecure remote URI schemes and documentation checks that prevent plaintext production examples from being reintroduced.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (25)

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
整体上,该脚本确实用于 Milvus 中的长期记忆 CRUD,并支持角色、事件、项目等维度分类,这与声明大体方向一致。但声明中突出的是“Milvus 向量数据库”能力,通常意味着使用向量表示和语义/相似度检索;而实际代码只创建了字符串与元数据字段,没有向量字段,也没有 search/ANN 检索逻辑,仅进行了普通过滤查询。因此描述对核心检索机制有实质性误导,属于描述与行为不完全一致的情况。加载 .env、命令行参数、集合初始化等属于支持性实现细节,不构成额外未声明风险。

Credential Access

High
Category
Privilege Escalation
Content
from typing import Dict, List, Optional, Any
from pathlib import Path

# 加载 .env 文件
def load_env_file():
    """加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
from typing import Dict, List, Optional, Any
from pathlib import Path

# 加载 .env 文件
def load_env_file():
    """加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
from typing import Dict, List, Optional, Any
from pathlib import Path

# 加载 .env 文件
def load_env_file():
    """加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
from typing import Dict, List, Optional, Any
from pathlib import Path

# 加载 .env 文件
def load_env_file():
    """加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
from typing import Dict, List, Optional, Any
from pathlib import Path

# 加载 .env 文件
def load_env_file():
    """加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
from typing import Dict, List, Optional, Any
from pathlib import Path

# 加载 .env 文件
def load_env_file():
    """加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
from typing import Dict, List, Optional, Any
from pathlib import Path

# 加载 .env 文件
def load_env_file():
    """加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
from typing import Dict, List, Optional, Any
from pathlib import Path

# 加载 .env 文件
def load_env_file():
    """加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
from typing import Dict, List, Optional, Any
from pathlib import Path

# 加载 .env 文件
def load_env_file():
    """加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
from typing import Dict, List, Optional, Any
from pathlib import Path

# 加载 .env 文件
def load_env_file():
    """加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
from typing import Dict, List, Optional, Any
from pathlib import Path

# 加载 .env 文件
def load_env_file():
    """加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
from typing import Dict, List, Optional, Any
from pathlib import Path

# 加载 .env 文件
def load_env_file():
    """加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"""加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
    script_dir = Path(__file__).parent
    env_file = script_dir / ".env"
    
    # 如果脚本目录没有,尝试加载当前工作目录的 .env
    if not env_file.exists():
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"""加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
    script_dir = Path(__file__).parent
    env_file = script_dir / ".env"
    
    # 如果脚本目录没有,尝试加载当前工作目录的 .env
    if not env_file.exists():
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"""加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
    script_dir = Path(__file__).parent
    env_file = script_dir / ".env"
    
    # 如果脚本目录没有,尝试加载当前工作目录的 .env
    if not env_file.exists():
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
"""加载 .env 文件到环境变量"""
    # 优先加载脚本所在目录的 .env
    script_dir = Path(__file__).parent
    env_file = script_dir / ".env"
    
    # 如果脚本目录没有,尝试加载当前工作目录的 .env
    if not env_file.exists():
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
script_dir = Path(__file__).parent
    env_file = script_dir / ".env"
    
    # 如果脚本目录没有,尝试加载当前工作目录的 .env
    if not env_file.exists():
        env_file = Path.cwd() / ".env"
Confidence
81% confidence
Finding
Falling back to loading .env from the current working directory introduces a configuration injection risk because execution context may be attacker-controlled or ambiguous. An attacker who can influence the working directory or place a malicious .env there could redirect MILVUS_URI, replace credentials, or cause the tool to connect to an attacker-controlled endpoint.

Lp3

Medium
Category
MCP Least Privilege
Confidence
87% confidence
Finding
The skill documents access to local .env files and operational scripts but declares no explicit tool scope or permissions boundary. In an agent environment, this can enable over-broad file/environment access and make it easier for the skill to read secrets or files beyond what users expect.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill encourages storing arbitrary memory content in an external Milvus service but does not prominently warn that user data will be transmitted off-platform and retained externally. This creates privacy and data-handling risk, especially if users store sensitive project, personal, or credential-adjacent information in long-term memory.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The skill documents delete/recreate flows that can remove existing records, but it does not provide an explicit warning or confirmation model around irreversible data loss. In an agent workflow, a user may trigger deletion or reinitialization without understanding that prior memory may be destroyed.

Natural-Language Policy Violations

Medium
Confidence
90% confidence
Finding
This markdown file contains all user-facing instructions and examples in Chinese, but it does not indicate that Chinese is optional or that the format is intended only for a Chinese-speaking audience. Under the language/locale policy, forcing a specific language without user opt-in can be a natural-language policy violation.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
The init_collection method supports dropping and recreating an existing collection when recreate=True, which permanently destroys stored memories. Although this is a legitimate admin feature, the script provides no explicit interactive confirmation, dry-run, or strong warning at the point of execution, so accidental invocation can cause irreversible data loss.

Natural-Language Policy Violations

Low
Confidence
84% confidence
Finding
The natural-language content of the skill is entirely in Chinese, including the top-level description and all operating instructions, with no indication that users may choose another language or that the skill is intentionally restricted to a Chinese-speaking context. Under the policy, forcing a specific language without user opt-in can be a locale/language policy issue.

Natural-Language Policy Violations

Low
Confidence
96% confidence
Finding
The file’s natural-language descriptions, user-facing messages, and CLI help are entirely in Chinese, which effectively imposes a single language on users without offering a language choice or documenting a justified locale restriction. This matches the language/locale policy violation category because no opt-in or alternative locale is provided.

Static analysis

No suspicious patterns detected.