Back to skill

Security audit

Firstprinciples thinking

Security checks for vulnerabilities and agentic risk

Overview

The skill’s reasoning purpose is mostly coherent, but its bundled scripts can silently save raw problem text and generated Markdown memory under the user’s home directory.

Review before installing or using the bundled scripts with sensitive personal, business, legal, financial, or strategic problems. The skill does not show exfiltration or destructive behavior, but its helper scripts can keep a long-lived local record of what you submit; use it only if that local persistence is acceptable and inspect or remove ~/.openclaw/workspace/memory/firstprinciples when needed.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • 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
  • 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)

T02 · Agent Memory Poisoning

Warning
Location
scripts/analyze_problem.py:40
Finding
Persistent Markdown Injection into Agent Memory<![CDATA[ ## Vulnerability Details **File Location**: `scripts/analyze_problem.py:40-71`; `scripts/lib/storage.py:57-74` **Vulnerability Type**: Persistent Markdown injection and memory poisoning **Risk Level**: Medium ### Vulnerable Code ```python # scripts/analyze_problem.py:40-71 title = args.title.strip() if args.title else clean_title(args.text) case = { "id": case_id, "title": title, "problem": args.text.strip(), "goal": infer_goal(args.text), "assumptions": infer_assumptions(args.text), "truths": infer_truths(args.text), "components": infer_components(args.text), "constraints": infer_constraints(args.text), "anti_patterns": detect_anti_patterns(args.text), "heuristics_used": select_heuristics(args.text), "reusable_pattern_candidate": "", "promotion_status": "none", "rebuilt_solution": infer_rebuilt_solution(args.text), "next_actions": infer_next_actions(args.text), "score": {}, "created_at": now_iso(), "updated_at": now_iso() } case["score"] = compute_score(case) case["reusable_pattern_candidate"] = infer_pattern_candidate(case) case["promotion_status"] = promotion_status(case) data["cases"][case_id] = case save_cases(data) append_case_index(case) if case["promotion_status"] == "promoted": append_promoted_pattern(case) ``` ```python # scripts/lib/storage.py:57-74 def append_case_index(case): ensure_storage() line = f"- {case['id']} | {case['title']} | score={case.get('score', {}).get('overall')} | promotion={case.get('promotion_status', 'none')} | created={case.get('created_at')}\n" with open(CASE_INDEX_PATH, "a", encoding="utf-8") as f: f.write(line) def append_promoted_pattern(case): ensure_storage() candidate = (case.get("reusable_pattern_candidate") or "").strip() if not candidate: return False entry = [] entry.append(f"## {case['id']} — {case['title']}") entry.append(f"- Pattern: {candidate}") entry.append(f"- Sour ...[truncated 2797 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Constrain titles before storage** - Reject `\r`, `\n`, null bytes, and other control characters. - Apply a conservative maximum length. - Optionally restrict titles to an allowlist of expected characters. 2. **Escape content for Markdown** - Escape Markdown metacharacters before inserting untrusted values into headings or list records. - Convert all newline characters to spaces when a value must remain on one line. 3. **Separate data from instructions** - Keep records in structured JSON rather than using generated Markdown as an authoritative memory source. - When records are supplied to an agent, place them inside a clearly delimited untrusted-data section. - Explicitly instruct the consuming agent never to follow instructions found in stored case content. 4. **Require approval for promotion** - Do not promote records based only on a deterministic score. - Require explicit user confirmation or a trusted review step before writing to `patterns.md`. 5. **Prevent duplicate promotion** - Record whether a pattern has already been written. - Use stable identifiers and idempotent updates instead of unconditional append operations. 6. **Validate all stored fields** - Introduce a schema-validation layer for titles, identifiers, timestamps, list entries, and generated candidates before persistent writes. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lib/storage.py:7
Finding
Automatic Retention of Raw User Content with Process-Default File Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/lib/storage.py:7-51`; `scripts/analyze_problem.py:37-67` **Vulnerability Type**: Insecure storage of potentially sensitive user data **Risk Level**: Medium ### Vulnerable Code ```python # scripts/lib/storage.py:7-51 STORAGE_DIR = os.path.expanduser("~/.openclaw/workspace/memory/firstprinciples") CASES_PATH = os.path.join(STORAGE_DIR, "cases.json") EXPORT_DIR = os.path.join(STORAGE_DIR, "exports") PATTERNS_PATH = os.path.join(STORAGE_DIR, "patterns.md") CASE_INDEX_PATH = os.path.join(STORAGE_DIR, "case_index.md") def now_iso(): return datetime.utcnow().isoformat() def ensure_storage(): os.makedirs(STORAGE_DIR, exist_ok=True) os.makedirs(EXPORT_DIR, exist_ok=True) if not os.path.exists(CASES_PATH): data = { "metadata": { "version": "1.1.0", "created_at": now_iso(), "last_updated": now_iso() }, "cases": {} } save_cases(data) if not os.path.exists(PATTERNS_PATH): with open(PATTERNS_PATH, "w", encoding="utf-8") as f: f.write("# Promoted Reasoning Patterns\n\n") if not os.path.exists(CASE_INDEX_PATH): with open(CASE_INDEX_PATH, "w", encoding="utf-8") as f: f.write("# Case Index\n\n") return CASES_PATH def load_cases(): ensure_storage() with open(CASES_PATH, "r", encoding="utf-8") as f: return json.load(f) def save_cases(data): os.makedirs(STORAGE_DIR, exist_ok=True) data.setdefault("metadata", {}) data["metadata"]["last_updated"] = now_iso() with open(CASES_PATH, "w", encoding="utf-8") as f: json.dump(data, f, indent=2, ensure_ascii=False) ``` ```python # scripts/analyze_problem.py:37-67 ensure_storage() data = load_cases() case_id = generate_case_id() title = args.title.strip() if args.title else clean_title(args.text) case = { "id": case_id, "title": title, "problem" ...[truncated 3085 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. **Make persistence explicit and optional** - Obtain explicit user consent before retaining a case. - Add a `--no-store` mode and consider making it the default. - Clearly document the storage location, retained fields, and retention duration. 2. **Apply owner-only permissions** - Create the storage and export directories with mode `0700`. - Create case, pattern, index, and export files with mode `0600`. - Verify and correct permissions on pre-existing files before use. 3. **Minimize retained content** - Avoid storing the complete raw problem unless it is necessary. - Offer redaction or summary-only storage. - Detect and warn about common sensitive-data formats before persistence. 4. **Provide lifecycle controls** - Add commands to delete individual cases and purge all stored data. - Support configurable expiration and automatic cleanup. - Prevent deleted content from remaining in indexes and promoted-pattern documents. 5. **Use safe update semantics** - Write updates to an owner-only temporary file in the same directory. - Flush and atomically replace `cases.json` to reduce corruption and unintended exposure. - Avoid following symbolic links when opening sensitive storage files where supported. 6. **Protect exported data** - Apply the same restrictive permissions and retention controls to the exports directory. - Warn users that exports can contain the original problem and generated analysis. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • 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 (16)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared purpose presents the skill as an intellectual framework for first-principles analysis. The supplied code does not implement reasoning logic, assumption-challenging, or solution synthesis; instead, it retrieves an existing case record from storage and formats it into a markdown document. While some exported field names relate to first-principles concepts, the code’s actual function is case export tooling. This is a materially different primary purpose and includes undeclared file I/O and CLI-based export behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
88% confidence
Finding
The declared description promises a broader first-principles reasoning capability: identifying fundamentals, challenging assumptions, and rebuilding better solutions. The supplied code only exposes a command-line tool that extracts inferred assumptions from input text via `infer_assumptions`. That is related to one subtask of the description, but it does not demonstrate the broader reasoning, truth decomposition, or solution rebuilding behavior claimed. There are no concerning undeclared permissions or resource accesses, but the primary purpose of the code chunk is materially narrower than the declared purpose.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents a conceptual reasoning skill focused on first-principles analysis. The supplied code does not implement any reasoning, problem decomposition, or assumption-challenging functionality. Instead, it performs a setup task: importing a storage utility, creating or verifying storage, and printing the resulting path. This is a materially different primary purpose and introduces filesystem/storage behavior that is not reflected in the declared description or permissions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description presents a conceptual reasoning aid, but the supplied code chunk does not perform reasoning, assumption-challenging, or solution reconstruction. Instead, it provides storage and bookkeeping utilities for cases and patterns, including filesystem writes and persistent memory management. Those are materially different capabilities from the declared purpose and involve resource access not reflected in the description or permissions.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
There is a clear mismatch between the declared description and the actual code behavior. The description claims a cognitive/problem-solving function centered on first-principles analysis, but the supplied code only retrieves case records from storage and outputs selected fields in JSON format. This is a materially different primary purpose and introduces undeclared data-access/reporting capability. No evidence in the code supports the claimed reasoning functionality.

Tp4

High
Category
MCP Tool Poisoning
Confidence
97% confidence
Finding
The declared description presents a reasoning methodology skill focused on first-principles analysis for solving problems. The code does not implement that kind of user-facing reasoning assistance. Instead, it performs backend processing of stored reasoning cases: loading data from storage, scoring a case, inferring reusable patterns, updating promotion status, saving changes, and optionally appending promoted patterns. This is a materially different primary purpose and includes undeclared data storage and workflow-management behavior.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description presents a cognitive/problem-solving skill focused on first-principles reasoning, with no triggers or permissions. The supplied code does not implement reasoning support or problem decomposition. Instead, it is a data-retrieval CLI tool that loads saved cases from storage, looks up a case by ID, and prints it. This is a materially different primary purpose and introduces an undeclared trigger (--id command-line argument) and storage access behavior unrelated to the description.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding
The declared description describes a conceptual problem-solving or reasoning skill, but the supplied code does not implement any first-principles analysis behavior. Instead, it functions as a simple data retrieval script for case scores. Its primary purpose, capabilities, and resource access pattern (loading stored cases and printing score data) are materially different from the declared purpose.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Description-Behavior Mismatch

Medium
Confidence
91% confidence
Finding
The skill is presented as a reasoning aid, but it defines persistent storage locations in the user's home directory for cases, exports, patterns, and indexes. That creates a local knowledge base of user-derived content not apparent from the description, which can retain sensitive prompts or derived reasoning artifacts beyond the user's expectation.

Context-Inappropriate Capability

Medium
Confidence
84% confidence
Finding
Automatically creating user-home storage and export directories is not clearly necessary for a first-principles thinking skill and increases the chance of silent retention of potentially sensitive data. Persistent storage in a fixed hidden directory can surprise users and may violate least-privilege and data-minimization expectations.

Description-Behavior Mismatch

Medium
Confidence
88% confidence
Finding
This code creates and appends durable index and pattern files that look like a persistent knowledge base, which materially expands the skill's behavior beyond simple reasoning assistance. Because titles and other case metadata are written into shared markdown artifacts, user-derived content may be retained and discoverable later without clear notice.

Vague Triggers

Low
Confidence
84% confidence
Finding
The 'Use this when the user' section describes broad situations such as wanting 'original thinking' or asking whether something is 'truly necessary, optimal, or possible.' These conditions are common across many ordinary conversations and do not define clear constraints or exclusions, which could lead to unintended invocation of the skill.

Missing User Warnings

Low
Confidence
85% confidence
Finding
The file writes index content to disk without any user-facing warning or confirmation in this code path. While not directly enabling code execution, silent writes reduce transparency and can cause users to unknowingly leave sensitive case metadata on the local filesystem.

Missing User Warnings

Low
Confidence
80% confidence
Finding
The save routine overwrites the persistent JSON case store without any visible disclosure to the user. This is primarily a transparency and integrity concern: users may not realize state is being updated on disk, and silent overwrites can complicate auditing or recovery of prior data.

Missing User Warnings

Low
Confidence
81% confidence
Finding
These append operations write user-derived titles, scores, timestamps, and reusable pattern content into markdown index files without any visible disclosure. Because the content is appended to aggregate files, sensitive or identifying information can accumulate over time and become easier to browse or exfiltrate locally.

Static analysis

No suspicious patterns detected.