Back to skill

Security audit

Agent Hivemind

Security checks for vulnerabilities and agentic risk

Overview

The skill is a networked recipe-sharing and recommendation CLI whose local inspection and remote submissions mostly match its stated purpose, with privacy-disclosure gaps users should understand before use.

Install only if you are comfortable with a third-party Supabase-backed service receiving the skill names installed in your OpenClaw workspace when you run suggestions, plus any play text, comments, replication notes, notification destinations, and preference data you explicitly submit. Use --dry-run before suggest, avoid entering secrets or proprietary workflow details, and consider pinning Python dependencies in your own environment.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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)

other

Warning
Location
scripts/hivemind.py:361
Finding
Undisclosed Transmission of the Installed Skill Inventory<![CDATA[ ## Vulnerability Details **File Location**: `scripts/hivemind.py:361-369`, `scripts/hivemind.py:741-762`, and `SKILL.md:151-158, 202` **Vulnerability Type**: Capability inventory disclosure and inaccurate privacy documentation **Risk Level**: Medium The `suggest` command enumerates installed OpenClaw skills from the local filesystem and sends the complete list to the configured Supabase backend. Although this data is necessary for the current server-side matching design, the privacy documentation does not include installed skills in its list of transmitted data and states that no filesystem scanning occurs. ### Vulnerable Code ```python def list_installed_skills() -> list[str]: """List skills installed in the current workspace.""" skills_dir = os.path.expanduser("~/.openclaw/workspace/skills") if not os.path.isdir(skills_dir): return [] return [ d for d in os.listdir(skills_dir) if os.path.isfile(os.path.join(skills_dir, d, "SKILL.md")) and not d.startswith("_") ] ``` The resulting inventory is transmitted by the `suggest` command: ```python async def cmd_suggest(ctx: AppContext, args: argparse.Namespace) -> None: my_skills = list_installed_skills() if not my_skills: print("No skills detected. Install some skills first!") return print(f"Your skills: {', '.join(my_skills)}") print() if getattr(args, "dry_run", False): print("[dry-run] Would query the hivemind backend for plays matching these skills.") print("[dry-run] No data submitted. Agent hash:", ctx.agent_hash) print("[dry-run] Backend:", ctx.supabase_url) return async with httpx.AsyncClient(timeout=20.0) as client: result = await api_post_rpc( client, ctx, "suggest_plays", { "agent_skills": my_skills, "match_count": args.limit, }, ) ``` The conflicting privacy ...[truncated 2543 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Explicitly list installed skill names under the `SKILL.md` “What data is sent” section. 2. Replace “No file system scanning” with a precise statement that the Skill enumerates names of installed Skill directories but does not read their contents beyond checking for `SKILL.md`. 3. Request explicit confirmation before the first inventory submission and display the exact list and destination. 4. Add an option allowing users to select which skill names may be submitted. 5. Consider performing matching locally after downloading a public play index, eliminating the need to disclose the full inventory. 6. If server-side matching is retained, investigate privacy-preserving representations and avoid persisting raw inventory data in backend logs. 7. Document retention, access controls, and deletion policies for submitted capability information. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/hivemind.py:344
Finding
Unpinned Python Dependencies and Runtime Embedding Model Resolution<![CDATA[ ## Vulnerability Details **File Location**: `scripts/hivemind.py:344-358`, `SKILL.md:11-13`, and `README.md:22-25` **Vulnerability Type**: Unpinned third-party packages and model artifacts **Risk Level**: Medium The project instructs users to install Python dependencies without version or artifact pinning. If `sentence-transformers` is installed, the implementation also resolves the `all-MiniLM-L6-v2` model by a mutable name without specifying a revision or verifying an artifact digest. ### Vulnerable Code and Installation Guidance ```python def generate_embedding(text: str) -> list[float] | None: """Generate 384-dim embedding locally using sentence-transformers.""" try: from sentence_transformers import SentenceTransformer model = SentenceTransformer("all-MiniLM-L6-v2") embedding = model.encode(text).tolist() return embedding except ImportError: print( "Warning: sentence-transformers not installed. Submitting without embedding.", file=sys.stderr, ) print("Install: pip install sentence-transformers", file=sys.stderr) return None ``` `SKILL.md` provides the following unpinned installation instruction: ```text ## Requirements - Python 3.10+ - `httpx` — `pip install httpx` - `openssl` CLI (pre-installed on macOS/Linux) — used for Ed25519 comment signing ``` `README.md` similarly states: ```text ## Install clawhub install agent-hivemind Requires Python 3.10+ and `httpx` (`pip install httpx`). ``` ### Technical Analysis Commands such as `pip install httpx` and `pip install sentence-transformers` resolve whatever compatible versions the package index serves at installation time. No lockfile, exact version constraint, or package hash is included in the audited artifact. Consequently, installations are not reproducible and cannot be reliably tied to versions reviewed by the Skill publisher. `SentenceTransformer("all-MiniLM-L6-v2")` may cause the de ...[truncated 2183 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Provide a lockfile containing exact, reviewed versions for direct and transitive Python dependencies. 2. Distribute installation requirements with exact version constraints and cryptographic hashes, and recommend installation using hash verification. 3. Add automated dependency vulnerability and provenance scanning to the release process. 4. Pin the embedding model to an immutable repository revision or commit. 5. Verify downloaded model files against publisher-maintained cryptographic digests before loading them. 6. Prefer safe, non-executable serialization formats and disable loading of remote custom model code. 7. Document that the embedding model may be retrieved from an external service and identify the service involved. 8. Offer an offline mode or bundle a verified model artifact where licensing and package-size constraints permit it. 9. Cache only verified artifacts and fail closed when integrity verification fails. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • YARA SignaturesMalware Match, Webshell Match, Cryptominer Match
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The documented purpose frames the skill as recommendation and evolution of skill combinations, but the described behavior extends into local environment inspection, remote API interaction, persistent key generation, notifications, and social/comment features. That mismatch can cause operators to grant or install the skill under an incomplete understanding of its true capabilities, which is dangerous because it combines local access, persistence, shell execution, and outbound network communication.

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
datetime import datetime, timezone
from pathlib import Path
from typing import Any
from urllib.parse import quote

import httpx

# Supabase anon key is public (read-only scope, RLS-protected). Hardcoded to avoid
# runtime config fetches that scanners flag as a remote-control vector.
SUPABASE_URL = "https://tjcryyjrjxbcjzybzdow.supabase.co"
SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InRqY3J5eWpyanhiY2p6eWJ6ZG93Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzM5NTIzNjUsImV4cCI6MjA4OTUyODM2NX0.G_PtxkbqXO6jz1mGUX7-afO1WlHl1c_z0_QBNbqLeJU"

CONFIG_FILE = Path.home() / ".openclaw" / "hivemind-config.env"
SCRIPT_DIR = Path(__file__).resolve().parent
KEY_PATH = SCRIPT_DIR / ".hivemind-key.pem"


def load_env_file(path: Path) -> dict[str, str]:
    values: dict[str, str] = {}
    if not path.exists():
        return values
    for raw in path.read_text(encoding="utf-8").splitlines():
        line = raw.strip()
        if not line or line.startswith("#"):
Confidence
80% confidence
Finding
YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
The README presents a narrowly scoped data collection statement for onboarding, but elsewhere documents remote writes of contributed plays, replications, comments, and notifications to Supabase services. This mismatch can mislead users about what data leaves the local environment and under what circumstances, weakening informed consent and trust boundaries even if submission is user-initiated.

Intent-Code Divergence

Medium
Confidence
95% confidence
Finding
The README says the hardcoded public anon key has read-only scope, yet the documented architecture states the agent performs writes through edge functions. Even if the key cannot directly write to tables, describing it as simply read-only obscures its role in invoking write-capable backend paths and may cause users or reviewers to underestimate remote modification capability.

Lp3

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding
The skill advertises shell, file read/write, environment access, and network behavior but declares no explicit tool scope or permissions boundary. That makes the effective trust surface much larger than the manifest suggests, increasing the chance an agent or user invokes it with broader capabilities than intended and reducing reviewability of sensitive operations.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The documentation contains conflicting statements about fallback identity generation: one section says it falls back to hostname and username, while the privacy section says a random per-session hash is used and no personal identifiers are involved. This inconsistency is security-relevant because hostname/username-derived identifiers can leak stable device- or user-linked information and defeat the stated anonymity model, leading users to consent under false privacy assumptions.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The implementation materially exceeds the narrow 'evolving skill combinations' description by adding comments, notifications, and preference management tied to a remote backend. Scope mismatch is dangerous because users and reviewers may underestimate data flows and granted trust, reducing informed consent around networked social and notification features.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def get_agent_hash() -> str:
    """Generate deterministic anonymous agent identity."""
    try:
        result = subprocess.run(
            ["openclaw", "status", "--json"],
            capture_output=True,
            text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
pass

    # Fallback for environments without `cryptography`.
    result = subprocess.run(
        ["openssl", "genpkey", "-algorithm", "ed25519", "-out", str(path)],
        capture_output=True,
        text=True,
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
try:
        msg_path.write_text(payload, encoding="utf-8")

        sign_cmd = subprocess.run(
            [
                "openssl",
                "pkeyutl",
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
raise RuntimeError(f"Failed to sign payload: {sign_cmd.stderr.strip()}")
        signature_hex = sig_path.read_bytes().hex()

        pub_cmd = subprocess.run(
            ["openssl", "pkey", "-in", str(KEY_PATH), "-pubout", "-outform", "DER"],
            capture_output=True,
        )
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The skill inspects the local workspace to enumerate installed skills, which is a form of host reconnaissance. In context, that list is later transmitted to the backend for suggestions, so local environment metadata is collected and disclosed beyond what the manifest description clearly justifies.

Missing User Warnings

Medium
Confidence
92% confidence
Finding
This command sends user-provided email or webhook destination data to the backend without a prominent runtime disclosure of what is being stored or where it is sent. Contact endpoints are sensitive metadata, and webhook URLs may embed secrets or internal infrastructure locations, making quiet transmission risky.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The contribute flow uploads free-form content plus inferred OS metadata to a remote backend without a clear runtime warning. Free-form text often contains operational details, identifiers, or proprietary workflow information, so silent upload increases risk of unintended data disclosure.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The suggest command transmits the locally detected installed-skill inventory to the backend without equivalent disclosure in the normal execution path. That inventory can reveal user capabilities, tooling choices, project focus, or internal workflows, making it sensitive environment metadata.

Static analysis

No suspicious patterns detected.