Back to skill

Security audit

Openclaw Auto Memory Skill

Security checks for vulnerabilities and agentic risk

Overview

The skill is a real persistent-memory integration, but it combines silent cross-session capture, automatic background jobs, global tool-governance hooks, credential-file access, and unpinned remote setup in ways users should review carefully before installing.

Only install this after reviewing the remote GitHub project and setup scripts, confirming the Sidecar URL is strictly local, using a dedicated low-privilege API key, and disabling or deleting any cron jobs or memory entries you do not want retained. Treat stored memories as sensitive because they may include identity, project details, infrastructure settings, and past session content.

Vulnerability Patterns
  • 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
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
Findings (5)

T01 · Skill Instruction Hijacking

Error
Location
scripts/policy_plugin.py:96
Finding

Global Agent Instruction and Tool-Execution Hijacking

Content
View full analysis
⚡ **New in v3.0.0 — Enforce Governance Layer** — A priority-based governance system that makes agent behavior more stable and safe. Enforce rules sit above memory and cannot be ignored by the agent. ``` `scripts/enforce_loader.py:90-107`: ```python def format_directives(rules: list[dict]) -> str: if not rules: return "" lines = [ "══════════════════════════════════════════════", "YOU MUST — ENFORCE RULES (Layer 1 — Prompt Governance)", "══════════════════════════════════════════════", ] for r in rules: p = r.get("priority", "high").upper() rule = r.get("rule", "") pol = r.get("policy", {}) tool = pol.get("tool", "*") action = pol.get("action", "allow") reason = pol.get("reason", "") lines.append(f" [{p}] {rule}") lines.append(f" tool={tool} action={action}") if reason: lines.append(f" → {reason}") ``` `scripts/policy_plugin.py:96-130`: ```python def load_from_skills(self, skills_dir: str | Path | None = None) -> int: """Scan all installed skills for enforce: frontmatter and register policies.""" if yaml is None: return 0 if skills_dir is None: hermes_home = os.environ.get("HERMES_HOME", os.path.expanduser("~/.hermes")) skills_dir = Path(hermes_home) / "skills" skil ...[truncated 3886 chars]
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Error
Location
SKILL.md:67
Finding

Execution of Mutable, Unverified Code from an External Repository

Content
View full analysis
Remediation
View remediation

T02 · Agent Memory Poisoning

Error
Location
SKILL.md:119
Finding

Automatic Cross-Session Memory and Scheduled Persistence with Contradictory Consent

Content
View full analysis
All three run silently — the user won't see cron output unless something fails. ``` `SKILL.md:176-203`: ```markdown **What to do:** 1. Silently run: `python C:\dev\HermesClawZero-ConfigSidecar ...[truncated 3453 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/memory.py:47
Finding

Arbitrary Endpoint Configuration Can Exfiltrate Memories and API Credentials over Plaintext HTTP

Content
View full analysis
tuple[str, str]: """Resolve API base URL and key from env vars or .env files.""" env_vars = {**os.environ} env_script = _load_dotenv(os.path.join(SCRIPT_DIR, ".env")) env_cwd = _load_dotenv(os.path.join(os.getcwd(), ".env")) api_base = ( env_vars.get("MEM_PUBLIC_URL") or env_script.get("MEM_PUBLIC_URL") or env_cwd.get("MEM_PUBLIC_URL", "http://localhost:8010") ) api_key = ( env_vars.get("API_KEY") or env_script.get("API_KEY") or env_cwd.get("API_KEY") or "" ) if not api_key: logger.warning("API_KEY not found in environment or .env files") return api_base.rstrip("/"), api_key API_BASE, API_KEY = _resolve_config() ``` `scripts/memory.py:81-93`: ```python def _api_call(method: str, path: str, **kwargs: Any) -> Any: """Make an authenticated request to the HermesClawZero Sidecar API.""" url = f"{API_BASE}{path}" headers = dict(kwargs.pop("headers", {})) headers.setdefault("X-API-Key", API_KEY) kwargs["headers"] = headers logger.debug("%s %s", method.upper(), url) try: r = requests.request(method, url, timeout=15, **kwargs) r.raise_for_status() return r.json() ``` `scripts/memory.py:110-143`: ```python def capture(text: str, scope_id: str | None = None) -> dict[str, Any]: """Persist a memory to the global chat namespace (always searchable).""" if not text or not text.strip(): raise ValueError("capture text must be non-empty") body: dict[str, Any] = {"text": text.strip()} if scope_id: body["scope_id"] = scope_id.strip()[:200] return _api_call("POST", "/ca ...[truncated 3060 chars]
Remediation
View remediation

T08 · Insecure Dependencies

Warning
Location
scripts/install.ps1:21
Finding

Unpinned Dependency Installation from the Active Python Package Index

Content
View full analysis
$null Write-Host " ✓ requests module installed" -ForegroundColor Green } catch { Write-Host " Installing requests module..." -ForegroundColor Yellow pip install requests 2>$null } ``` ### Technical Analysis When `requests` cannot be imported, the installer invokes the ambient `pip` executable and installs the latest package version accepted by the configured package index. No version constraint, lockfile, package hash, trusted index configuration, or virtual environment is used. The command also assumes that `pip` belongs to the same interpreter invoked as `python`. A manipulated `PATH` can cause a different or malicious executable to run. Package installation can execute package build hooks and modifies the active Python environment. This is an unsafe supply-chain practice even though no evidence in the reviewed package establishes that the legitimate `requests` package itself is malicious. ### Attack Path 1. `requests` is absent from the active Python environment. 2. An attacker controls or influences `PATH`, pip configuration, DNS/network access, or the configured package index. 3. The installer invokes `pip install requests`. 4. A substituted or compromised package is downloaded and installed. 5. Package installation or later import executes attacker-controlled code with the installer user’s privileges. ### Impact Assessment Successful exploitation provides code execution under the account running the installer and can modify the active Python environment. It may affect other applications that share that interpreter and can expose environment variables, `.env` files, Sidecar credentials, and locally accessible user data. ]]>
Remediation
View remediation
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 Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (46)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The document describes runtime policy enforcement, rule loading from frontmatter, and action blocking/prompting, but these controls are not foregrounded as a major behavior of the skill. Hidden policy injection into agent behavior is risky because it can alter tool access, approvals, and auditing in ways users may not anticipate.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The document describes runtime policy enforcement, rule loading from frontmatter, and action blocking/prompting, but these controls are not foregrounded as a major behavior of the skill. Hidden policy injection into agent behavior is risky because it can alter tool access, approvals, and auditing in ways users may not anticipate.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The document describes runtime policy enforcement, rule loading from frontmatter, and action blocking/prompting, but these controls are not foregrounded as a major behavior of the skill. Hidden policy injection into agent behavior is risky because it can alter tool access, approvals, and auditing in ways users may not anticipate.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
93% confidence
Finding

This permission explicitly allows reading a .env file to obtain API_KEY and MEM_PUBLIC_URL values, which are commonly used to store secrets. Granting a skill filesystem access to credential material creates a direct secret-exposure path if the skill is compromised, over-collects data, or forwards values to the sidecar or other components.

Content

Scanner excerpt · permissions.yaml (reported line 21)May include surrounding context.

yaml
- http
    justification: "Required to capture/search/autosave memories via Sidecar API"

  # Filesystem access to .env config
  - id: env-read
    description: "Read .env files for API_KEY and MEM_PUBLIC_URL configuration"
    type: filesystem

Credential Access

High
Category
Privilege Escalation
Confidence
95% confidence
Finding

The filesystem read permission around the env-read block is a real credential-access concern because it authorizes access to configuration storage that likely contains secrets. In a multi-agent persistent-memory context, secret exposure is more dangerous because captured credentials could be retained, shared across skills, or later surfaced through memory search.

Content

Scanner excerpt · permissions.yaml (reported line 23)May include surrounding context.

yaml
# Filesystem access to .env config
  - id: env-read
    description: "Read .env files for API_KEY and MEM_PUBLIC_URL configuration"
    type: filesystem
    access: read
    paths:

Credential Access

High
Category
Privilege Escalation
Confidence
94% confidence
Finding

The explicit path entry for ".env" confirms the skill can read a well-known secret container from the project directory. Because this skill is a unified memory platform with persistent and cross-skill sharing features, any accidental ingestion or misuse of secrets from .env materially raises the risk of long-term credential compromise and lateral exposure.

Content

Scanner excerpt · permissions.yaml (reported line 27)May include surrounding context.

yaml
type: filesystem
    access: read
    paths:
      - ".env"
    justification: "Required to load API credentials from project or script directory"

  # Background cron jobs (user must explicitly opt in)

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/install.ps1 (reported line 32)May include surrounding context.

text
# 3. Check .env config
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$envPath = Join-Path $scriptDir "..\.env"
if (Test-Path $envPath) {
    Write-Host "  ✓ .env found" -ForegroundColor Green
} else {

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/memory.py (reported line 49)May include surrounding context.

python
# 3. Check .env config
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$envPath = Join-Path $scriptDir "..\.env"
if (Test-Path $envPath) {
    Write-Host "  ✓ .env found" -ForegroundColor Green
} else {

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · CHANGELOG.md (reported line 38)May include surrounding context.

md
def _load_dotenv(path: str) -> dict[str, str]:
    """Minimal .env parser — no external dependencies needed."""
    env: dict[str, str] = {}
    if not os.path.isfile(path):
        return env

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 122)May include surrounding context.

md
def _load_dotenv(path: str) -> dict[str, str]:
    """Minimal .env parser — no external dependencies needed."""
    env: dict[str, str] = {}
    if not os.path.isfile(path):
        return env

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 163)May include surrounding context.

md
def _load_dotenv(path: str) -> dict[str, str]:
    """Minimal .env parser — no external dependencies needed."""
    env: dict[str, str] = {}
    if not os.path.isfile(path):
        return env

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/install.ps1 (reported line 30)May include surrounding context.

text
def _load_dotenv(path: str) -> dict[str, str]:
    """Minimal .env parser — no external dependencies needed."""
    env: dict[str, str] = {}
    if not os.path.isfile(path):
        return env

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/install.ps1 (reported line 34)May include surrounding context.

text
def _load_dotenv(path: str) -> dict[str, str]:
    """Minimal .env parser — no external dependencies needed."""
    env: dict[str, str] = {}
    if not os.path.isfile(path):
        return env

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/install.ps1 (reported line 36)May include surrounding context.

text
def _load_dotenv(path: str) -> dict[str, str]:
    """Minimal .env parser — no external dependencies needed."""
    env: dict[str, str] = {}
    if not os.path.isfile(path):
        return env

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/memory.py (reported line 29)May include surrounding context.

python
def _load_dotenv(path: str) -> dict[str, str]:
    """Minimal .env parser — no external dependencies needed."""
    env: dict[str, str] = {}
    if not os.path.isfile(path):
        return env

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/memory.py (reported line 47)May include surrounding context.

python
def _load_dotenv(path: str) -> dict[str, str]:
    """Minimal .env parser — no external dependencies needed."""
    env: dict[str, str] = {}
    if not os.path.isfile(path):
        return env

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · scripts/memory.py (reported line 64)May include surrounding context.

python
def _load_dotenv(path: str) -> dict[str, str]:
    """Minimal .env parser — no external dependencies needed."""
    env: dict[str, str] = {}
    if not os.path.isfile(path):
        return env

Env Variable Harvesting

High
Category
Data Exfiltration
Confidence
60% confidence
Finding

Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.

Content

Scanner excerpt · scripts/memory.py (reported line 48)May include surrounding context.

python
def _resolve_config() -> tuple[str, str]:
    """Resolve API base URL and key from env vars or .env files."""
    env_vars = {**os.environ}
    env_script = _load_dotenv(os.path.join(SCRIPT_DIR, ".env"))
    env_cwd = _load_dotenv(os.path.join(os.getcwd(), ".env"))

Credential Access

High
Category
Privilege Escalation
Confidence
68% confidence
Finding

Loading a .env file from the current working directory can cause the program to consume attacker-controlled configuration when run inside an untrusted repository or directory. An attacker could plant a .env that overrides MEM_PUBLIC_URL and API_KEY, causing memory contents to be sent to an attacker-controlled server or using unintended credentials.

Content

Scanner excerpt · scripts/memory.py (reported line 50)May include surrounding context.

python
"""Resolve API base URL and key from env vars or .env files."""
    env_vars = {**os.environ}
    env_script = _load_dotenv(os.path.join(SCRIPT_DIR, ".env"))
    env_cwd = _load_dotenv(os.path.join(os.getcwd(), ".env"))

    api_base = (
        env_vars.get("MEM_PUBLIC_URL")

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · CHANGELOG.md (reported line 200)May include surrounding context.

md
# secrets.yaml
# Environment secrets required by hermesclawzero-auto-memory.

version: 1

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · README.md (reported line 148)May include surrounding context.

md
# secrets.yaml
# Environment secrets required by hermesclawzero-auto-memory.

version: 1

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · secrets.yaml (reported line 1)May include surrounding context.

yaml
# secrets.yaml
# Environment secrets required by hermesclawzero-auto-memory.

version: 1

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The README explicitly states that the agent will silently load and automatically capture conversational data across sessions without prominently warning users about persistence, privacy implications, or review/disable controls. Even if data stays local, storing personal and project context without clear informed consent can lead to unexpected retention and disclosure of sensitive information.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill behavior normalizes silent collection and replay of user-provided personal and project data across sessions without explicit per-item confirmation or prominent consent language. This can cause the system to retain sensitive facts the user did not realize were being stored and later surface them in a different context.

Content

No source excerpt is available for this finding.

Ssd 3

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The example workflow demonstrates storing a user's name, project, and preferences silently, then replaying them later. This creates a concrete privacy risk because identity and work context may be persisted and disclosed unexpectedly, especially on shared machines or in multi-tenant environments.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.