Back to skill

Security audit

Rookie Memory

Security checks for vulnerabilities and agentic risk

Overview

This memory skill is purpose-aligned, but it needs review because it can persist conversation content, send it to a remote embedding API, and automatically use a local API key without clear disclosure.

Install only if you are comfortable with conversation memory being stored durably and sent to the configured Zhiyi embedding provider. Do not store secrets, credentials, regulated data, or private personal data unless you have consent and a retention plan. Prefer disabling or constraining remote embeddings, validating the endpoint host, using a narrowly scoped API key, and running cleanup only after dry-run review and backup/export if the memories matter.

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 (1)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/memory_manager.py:28
Finding

Undisclosed transmission of stored conversations with unrestricted embedding endpoint override

Content
View full analysis
list: """ 调用 GLM embedding API 生成向量 使用 embedding-3 模型 """ global ZHIYI_API_KEY # 尝试从 OpenClaw 配置获取 API Key if not ZHIYI_API_KEY: config_path = Path('/root/.openclaw/openclaw.json') if config_path.exists(): with open(config_path) as f: config = json.load(f) # 从 zhiyi provider 获取 API key if 'auth' in config and 'profiles' in config['auth']: for profile_name, profile in config['auth']['profiles'].items(): if 'zhiyi' in profile_name.lower() or profile.get('provider') == 'zhiyi': ZHIYI_API_KEY = profile.get('apiKey', '') break # 或者从 zhiyi provider 的 models 配置获取 if not ZHIYI_API_KEY and 'models' in config and 'providers' in config['models']: zhiyi_cfg = config['models']['providers'].get('zhiyi', {}) ZHIYI_API_KEY = zhiyi_cfg.get('apiKey', '') if not ZHIYI_API_KEY: print("✗ 无法获取 ZHIYI API Key") return None url = f"{ZHIYI_BASE_URL}/embeddings" headers = { "Authorization": f"Bearer {ZHIYI_API_KEY}", "Content-Type": "application/json" } data = { "model": "embedding-3", "input": text } try: response = requests.post(url, headers=headers, json=data, timeout=30) response.raise_for_status() result = response.jso ...[truncated 5306 chars]
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (29)

Tainted flow: 'url' from os.environ.get (line 60, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Confidence
96% confidence
Finding

The request target is derived from an environment-controlled base URL and the request includes a bearer token plus user memory content. In this skill context, that means an attacker who can influence environment variables or deployment config can redirect sensitive conversation data and credentials to an attacker-controlled endpoint, making this more than a generic SSRF-style issue.

Content

Scanner excerpt · scripts/memory_manager.py (reported line 71)May include surrounding context.

python
}
    
    try:
        response = requests.post(url, headers=headers, json=data, timeout=30)
        response.raise_for_status()
        result = response.json()
        if 'data' in result and len(result['data']) > 0:

Ssd 3

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The autosave workflow copies recent conversation content into long-term vector storage, decision files, and daily logs, substantially broadening exposure and retention of sensitive text. In a memory skill this is especially dangerous because users are likely to place confidential information into conversations, and autosave occurs without granular review of each destination.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill instructs use of commands that read and write files, access environment-specific interpreters, and likely invoke network-capable dependencies such as ChromaDB-backed tooling, yet it declares no explicit tool scope or permission boundaries. That creates an unsafe trust model where an agent may execute broader capabilities than the skill metadata communicates, increasing the chance of unintended file access, persistence, or external connectivity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill promotes automatic saving of conversation-derived memory and generation of log files without a prominent privacy notice, retention policy, or consent step. Users may unknowingly persist sensitive prompts, personal data, credentials, or business information to local storage, creating confidentiality and compliance risks.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill explicitly encourages retention of stable facts such as identity information and creation of daily logs, but it provides no data minimization, secret filtering, or sensitivity classification rules. In an agent context, that can cause broad storage of personal, confidential, or regulated data that was only intended for transient use.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The autosave process reads short-term conversation memory, summarizes it, updates decision records, and persists content into logs and long-term storage. Without sensitivity checks or user approval, this creates a strong risk of propagating confidential user inputs into multiple durable locations, magnifying exposure if the workspace is accessed, backed up, or synced elsewhere.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The cleanup workflow includes a destructive delete operation for stored memories, but the documentation does not prominently warn about irreversible data loss before presenting the live command. An operator could run the command expecting maintenance behavior and unintentionally remove important memory records.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The documentation instructs users to store arbitrary memory content, including examples containing personal information and user preferences, but provides no guidance on avoiding sensitive data, obtaining consent, or handling retention securely. In a memory-management skill for AI agents, this increases the likelihood that operators will persist private conversation data by default, creating privacy and compliance risks if the stored data is exposed or misused.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The integration examples and data-structure sections show raw user messages being written to persistent local files and a vector store, but they omit any warning about retention, local disk persistence, or exposure of conversation contents. Because this skill is specifically designed to bootstrap, autosave, and retrieve memory for an AI agent, the context makes silent persistence more dangerous: developers may integrate it assuming ephemeral handling when the system actually creates durable records.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill reads API credentials from environment variables and a local OpenClaw config file, expanding its access to secrets beyond user-supplied inputs. In an agent-skill context, automatic credential discovery is sensitive because users may not expect the skill to read host-level config and use those secrets for remote requests.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script accesses credentials from environment variables and local host configuration without prominently warning the user. In an agent ecosystem, undeclared secret access is risky because users may treat skills as limited to workspace data, not host-level auth material.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill transmits memory content to a remote embedding API, but the description does not clearly disclose this external data flow. Because this is a memory-management skill handling conversational data, undisclosed off-box transmission materially increases privacy and data-exfiltration risk.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The design automatically retains, summarizes, and processes conversation content, which naturally increases the amount of sensitive natural-language data stored and handled. In this file, that risk is amplified because content may later be logged, persisted across tiers, and transmitted externally for embeddings.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
95% confidence
Finding

This line performs external transmission of text to a remote API while authenticated with a bearer token. In the context of a memory-management skill, outbound transfer of remembered conversation content is security-relevant because it can expose sensitive user data to third-party infrastructure.

Content

Scanner excerpt · scripts/memory_manager.py (reported line 71)May include surrounding context.

python
}
    
    try:
        response = requests.post(url, headers=headers, json=data, timeout=30)
        response.raise_for_status()
        result = response.json()
        if 'data' in result and len(result['data']) > 0:

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

Autosave can send conversation contents to the embedding API without an explicit warning or confirmation step. Given this skill's purpose is storing and processing user memory, silently exporting those contents to a third party meaningfully increases privacy and compliance risk.

Content

No source excerpt is available for this finding.

Tainted flow: 'config_json' from os.environ.get (line 142, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/memory_manager.py (reported line 143)May include surrounding context.

python
"""保存配置文件"""
    # 使用 JSON 而非 YAML,减少依赖
    config_json = CONFIG_FILE.with_suffix('.json')
    with open(config_json, 'w') as f:
        json.dump(config, f, indent=2, ensure_ascii=False)
    print(f"✓ 已保存配置: {config_json}")

Tainted flow: 'SLIDING_WINDOW_FILE' from os.environ.get (line 87, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/memory_manager.py (reported line 159)May include surrounding context.

python
# 创建短期记忆文件
    if not SLIDING_WINDOW_FILE.exists():
        with open(SLIDING_WINDOW_FILE, 'w') as f:
            json.dump({'messages': [], 'updated_at': datetime.now().isoformat()}, f, indent=2, ensure_ascii=False)
        print(f"✓ 已创建短期记忆: {SLIDING_WINDOW_FILE}")

Tainted flow: 'SLIDING_WINDOW_FILE' from os.environ.get (line 87, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/memory_manager.py (reported line 195)May include surrounding context.

python
# 创建短期记忆文件
    if not SLIDING_WINDOW_FILE.exists():
        with open(SLIDING_WINDOW_FILE, 'w') as f:
            json.dump({'messages': [], 'updated_at': datetime.now().isoformat()}, f, indent=2, ensure_ascii=False)
        print(f"✓ 已创建短期记忆: {SLIDING_WINDOW_FILE}")

Tainted flow: 'SLIDING_WINDOW_FILE' from os.environ.get (line 87, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/memory_manager.py (reported line 799)May include surrounding context.

python
# 创建短期记忆文件
    if not SLIDING_WINDOW_FILE.exists():
        with open(SLIDING_WINDOW_FILE, 'w') as f:
            json.dump({'messages': [], 'updated_at': datetime.now().isoformat()}, f, indent=2, ensure_ascii=False)
        print(f"✓ 已创建短期记忆: {SLIDING_WINDOW_FILE}")

Tainted flow: 'SLIDING_WINDOW_FILE' from os.environ.get (line 87, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/memory_manager.py (reported line 838)May include surrounding context.

python
# 创建短期记忆文件
    if not SLIDING_WINDOW_FILE.exists():
        with open(SLIDING_WINDOW_FILE, 'w') as f:
            json.dump({'messages': [], 'updated_at': datetime.now().isoformat()}, f, indent=2, ensure_ascii=False)
        print(f"✓ 已创建短期记忆: {SLIDING_WINDOW_FILE}")

Tainted flow: 'summary_file' from os.environ.get (line 1069, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
65% confidence
Finding

Data from a source is assigned to a variable that is later passed to a sink, creating a variable-mediated taint flow.

Content

Scanner excerpt · scripts/memory_manager.py (reported line 229)May include surrounding context.

python
}
    data['summaries'].append(new_summary)
    
    with open(summary_file, 'w') as f:
        json.dump(data, f, indent=2, ensure_ascii=False)
    
    print(f"✓ 已添加中期记忆: {summary_file}")

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

Autosave performs additional persistence operations—updating permanent decision files and generating daily logs—that go beyond the manifest's high-level description. In a memory skill, silent expansion of retention scope is dangerous because users may disclose sensitive information assuming transient handling.

Content

No source excerpt is available for this finding.

Tainted flow: 'l1_decisions_file' from os.environ.get (line 925, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
83% confidence
Finding

Autosave writes conversation-derived 'decision' entries into a permanent file automatically, which can preserve sensitive data and embed misleading or attacker-influenced content into long-lived memory. The security issue is the silent durable persistence of conversation material more than the raw path taint.

Content

Scanner excerpt · scripts/memory_manager.py (reported line 764)May include surrounding context.

python
new_entry = f"\n\n## {date_str} (自动保存)\n\n"
        new_entry += "\n".join(decisions_found)
        
        with open(l1_decisions_file, 'a', encoding='utf-8') as f:
            f.write(new_entry)
        
        print(f"   ✓ 已更新 key-decisions.md (新增 {len(decisions_found)} 条)")

Tainted flow: 'log_file' from os.environ.get (line 992, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
80% confidence
Finding

Autosave appends recent conversation content into a daily log file under a path derived from the workspace location, creating durable plaintext copies of potentially sensitive user data. In this skill context, the bigger issue is not path taint alone but that autosave silently persists private conversation fragments beyond the described memory behavior.

Content

Scanner excerpt · scripts/memory_manager.py (reported line 793)May include surrounding context.

python
log_entry += "\n".join([f"  • {m.get('content', '')[:100]}..." for m in short_memories[-5:]])
    log_entry += "\n"
    
    with open(log_file, 'a', encoding='utf-8') as f:
        f.write(log_entry)
    
    print(f"   ✓ 已生成日志: {log_file}")

Tainted flow: 'l1_decisions_file' from os.environ.get (line 925, credential/environment) → open (file write)

Medium
Category
Data Flow
Confidence
82% confidence
Finding

The code appends extracted decision content from conversations into a permanent markdown file without user confirmation. In this skill context that creates unreviewed durable storage of potentially sensitive or prompt-injected text, and the path is influenced by workspace configuration.

Content

Scanner excerpt · scripts/memory_manager.py (reported line 943)May include surrounding context.

python
new_entry = f"\n\n## {date_str} (手动提取)\n\n"
    new_entry += "\n".join(decisions_found)
    
    with open(l1_decisions_file, 'a', encoding='utf-8') as f:
        f.write(new_entry)
    
    print(f"✓ 已更新 key-decisions.md (新增 {len(decisions_found)} 条)")

Static analysis

No suspicious patterns detected.