Back to skill

Security audit

Memory Poison Auditor

Security checks for vulnerabilities and agentic risk

Overview

This memory-auditing skill is mostly coherent, but its optional AI review can send sensitive memory content to a configurable external service and its cleaning mode can rewrite memory files.

Install only if you are comfortable with a memory auditor that can write reports, create backups, rewrite memory files when clean --apply is used, and send suspicious memory excerpts to an external AI service when --with-ai is enabled. Prefer local scan mode, avoid --with-ai for private memory unless the endpoint and API key are trusted, and review reports manually before running clean --apply.

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

Warning
Location
lib/audit.py:181
Finding

Optional AI Review Can Disclose Sensitive Memory Content and API Credentials to a Configurable External Endpoint

Content
View full analysis

Vulnerability Details

File Location: lib/audit.py, lines 181-217
Vulnerability Type: External disclosure of sensitive memory data and insufficient endpoint validation
Risk Level: Medium

python
api_key = os.environ.get("ZENMUX_API_KEY")
if not api_key:
    return {"enabled": False, "available": False, "summary": "AI review skipped because ZENMUX_API_KEY is not configured."}

base_url = os.environ.get("ZENMUX_ANTHROPIC_BASE_URL", "https://zenmux.ai/api/anthropic")
model = os.environ.get("MEMORY_AUDITOR_MODEL") or os.environ.get("ZENMUX_ANTHROPIC_MODEL", "anthropic/claude-opus-4.6")
payload = {
    "path": str(block.path),
    "line_range": [block.start_line, block.end_line],
    "static_result": static_result,
    "excerpt": block.text[: int(os.environ.get("MEMORY_AUDITOR_AI_MAX_CHARS", "10000"))],
}
system_prompt = (
    "You are auditing an OpenClaw memory block for memory poisoning.\n"
    "Decide whether the block acts like factual memory or hidden steering/policy injection.\n"
    "Return strict JSON only with keys: risk_score, recommendation, summary, evidence.\n"
    "recommendation must be PASS, WARN, or BLOCK."
)
request = urllib.request.Request(
    f"{base_url.rstrip('/')}/v1/messages",
    data=json.dumps(
        {
            "model": model,
            "system": system_prompt,
            "messages": [{"role": "user", "content": json.dumps(payload, ensure_ascii=False)}],
            "temperature": 0,
            "max_tokens": 700
        }
    ).encode("utf-8"),
    headers={
        "Content-Type": "application/json",
        "x-api-key": api_key,
        "anthropic-version": "2023-06-01"
    },
    method="POST"
)
try:
    with urllib.request.urlopen(request, timeout=45) as response:
        parsed = json.loads(response.read().decode("utf-8"))

Technical Analysis

When the operator enables --with-ai, the Skill sends suspicious m ...[truncated 2327 chars]

Remediation
View remediation

Remediation Suggestions

  • Clearly disclose that --with-ai exports memory content, file paths, and analysis metadata to an external provider.
  • Require explicit confirmation that displays the resolved destination before the first transmission.
  • Restrict destinations to an administrator-configured HTTPS allowlist.
  • Reject plaintext HTTP, embedded URL credentials, redirects to unapproved hosts, and unexpected schemes.
  • Do not send the provider API key to a host that has not been explicitly trusted.
  • Redact likely credentials, tokens, personal information, and unnecessary path details before constructing the request.
  • Send only the minimum excerpt necessary for classification and impose a non-bypassable maximum size.
  • Provide a local-only review mode for sensitive environments.
  • Use a dedicated, least-privileged API credential with tight quotas and rotation support.
  • Record destination and disclosure metadata in the report without recording the secret itself.

T09 · Insecure Skill Coding Practices

Warning
Location
lib/audit.py:318
Finding

Non-Unique Backup Names Can Overwrite Recovery Copies During Destructive Cleaning

Content
View full analysis

Vulnerability Details

File Location: lib/audit.py, lines 318-320
Vulnerability Type: Backup filename collision and unsafe destructive file handling
Risk Level: Medium

python
backup_path = backups_dir / f"{path.name}.{datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%SZ')}.bak"
shutil.copy2(path, backup_path)
path.write_text("\n".join(keep).rstrip() + "\n", encoding="utf-8")

Technical Analysis

The backup filename consists only of the source file's basename and a timestamp with one-second resolution. It does not include the source directory, a unique identifier, a content hash, or a collision counter.

If multiple scanned files have the same basename and are cleaned within the same second, they resolve to the same backup path. shutil.copy2 overwrites an existing destination file by default. Consequently, a later backup can silently replace an earlier file's recovery copy before the earlier source has any guaranteed independent backup.

The source is then rewritten in place. This makes the collision particularly serious because cleaning is destructive and the documentation promises that backups are created before rewriting suspicious blocks.

Attack Path

  1. The selected scan tree contains two or more files with the same basename, such as separate files named MEMORY.md.
  2. Each file contains a block classified as WARN or BLOCK.
  3. The operator runs clean --apply.
  4. The files are processed during the same UTC second.
  5. Each backup calculation produces the same destination filename.
  6. A later shutil.copy2 call overwrites the backup created for an earlier source file.
  7. The original source files are rewritten with suspicious ranges removed.
  8. At least one cleaned file no longer has its own recoverable original backup.

Impact Assessment

This issue can cause permanent loss of original memory content and undermine recovery from false-positive cleaning. It does not grant ...[truncated 352 chars]

Remediation
View remediation

Remediation Suggestions

  • Preserve the source file's relative directory structure inside the backup directory.
  • Add a collision-resistant identifier such as a UUID, cryptographic path hash, or nanosecond-resolution component.
  • Create backups with exclusive semantics so an existing backup can never be silently overwritten.
  • Verify that the backup exists, is readable, and matches the source content before rewriting the original file.
  • Write cleaned content to a temporary file in the same filesystem, flush and synchronize it, and then atomically replace the source.
  • Abort cleaning for a file if any backup or verification step fails.
  • Record the original absolute path, content hash, backup path, and removed ranges in a recovery manifest.
  • Add tests covering duplicate basenames, rapid multi-file cleaning, interrupted writes, and existing backup destinations.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Memory PoisoningPersistent Context Injection, Context Window Stuffing, Memory Manipulation
  • Taint TrackingDirect Taint Flow, Variable-Mediated Taint Flow, Credential Exfiltration Chain
Findings (13)

Tainted flow: 'request' from os.environ.get (line 219, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Confidence
98% confidence
Finding

The code builds an outbound HTTP request using environment-controlled configuration such as the base URL and then sends memory excerpts, file paths, and static analysis results to that remote endpoint. This creates a real exfiltration channel for potentially sensitive local memory contents and allows redirection to an attacker-controlled service if environment variables are manipulated.

Content

Scanner excerpt · lib/audit.py (reported line 238)May include surrounding context.

python
method="POST"
    )
    try:
        with urllib.request.urlopen(request, timeout=45) as response:
            parsed = json.loads(response.read().decode("utf-8"))
        raw_content = "".join(part.get("text", "") for part in parsed.get("content", []) if isinstance(part, dict))
        raw_content = raw_content.strip()

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding

The skill is presented as a memory auditor, but the documented commands include optional AI review and one-click cleaning that can transmit memory content to third parties and rewrite local memory files. Because memory stores may contain sensitive conversation history, hidden prompts, credentials, or private user data, undeclared network exfiltration and modification behavior create substantial confidentiality and integrity risk.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The function reads an API key from the environment and transmits memory block excerpts plus analysis metadata to a remote API. Because memory stores can contain sensitive instructions, user data, or internal context, this is a significant confidentiality risk not justified by a purely local auditing description.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

High
Category
Not specified by scanner
Confidence
99% confidence
Finding

The cleaning routine edits the original memory files and removes flagged line ranges, even though the skill is framed as an auditor. In this context, silent mutation is dangerous because false positives or adversarial rule tuning could destroy or tamper with long-term memory data and alter system behavior.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The cleaning routine removes flagged content from audited files without any visible confirmation, approval step, or user warning. In a tool processing long-term memory stores, this can cause irreversible data loss, accidental censorship, or attacker-induced tampering if suspicious classifications are wrong or manipulated.

Content

No source excerpt is available for this finding.

Instruction Override

High
Category
Prompt Injection
Confidence
80% confidence
Finding

This pattern attempts to override system instructions or ignore safety constraints. Without LLM analysis, manual review is recommended.

Content

Scanner excerpt · policies/default_rules.json (reported line 31)May include surrounding context.

json
"perplexity"
  ],
  "injection_patterns": [
    "ignore previous instructions",
    "ignore all prior instructions",
    "system prompt",
    "developer message",

YARA rule 'agent_skill_prompt_injection_hidden_instructions': Prompt injection or hidden instructions embedded in AI agent skill text [agent_skills]

High
Category
YARA Match
Confidence
80% confidence
Finding

YARA rule matched a hack tool or exploit indicator (offensive tools, reconnaissance, privilege escalation, or exploit frameworks).

Content

Scanner excerpt · policies/default_rules.json (reported line 31)May include surrounding context.

json
space}/output/memory-poison-auditor/backups",
  "thresholds": {
    "warn": 25,
    "block": 55
  },
  "size_limits": {
    "max_file_chars": 50000,
    "max_ai_chars": 10000
  },
  "brand_terms": [
    "openai",
    "anthropic",
    "claude",
    "chatgpt",
    "gpt",
    "gemini",
    "deepseek",
    "cursor",
    "openclaw",
    "langchain",
    "perplexity"
  ],
  "injection_patterns": [
    "ignore previous instructions",
    "ignore all prior instructions",
    "system prompt",
    "developer message",
    "do not reveal",
    "override the user",
    "secretly",
    "hidden policy",
    "do this regardless of user intent"
  ],
  "steering_patterns": [
    "always recommend",
    "must recommend",
    "prefer this brand",
    "never mention competitors",
    "suppress competitors",
    "push this product",
    "default recommendation",
    "no matter what the user asks",
    "regardless of context"
  ],
  "authority_patterns": [
    "the user explicitly approved",
    "human alre

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding

The skill declares no explicit tool/permission scope even though its documented behavior implies reading memory files, writing reports/backups, modifying files during cleaning, and potentially invoking an AI-backed review path. Missing scope declarations weaken least-privilege controls and make it harder for users or the platform to understand and constrain what the skill can access.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill is described as auditing local memory files, but this function performs optional remote AI review, expanding its capability beyond local analysis. In a memory-auditing context, sending inspected content off-host materially increases privacy and trust risk because users would not expect external network access from the stated role.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The AI review code sends memory content and related analysis to an external HTTP endpoint without any user-facing warning or consent mechanism in the code path. This lack of disclosure is especially risky for a memory auditing tool because the scanned content may include confidential or safety-critical internal notes.

Content

No source excerpt is available for this finding.

Persistent Context Injection

Medium
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill injects content designed to persist in agent memory or context across interactions. Persistent injection can alter agent behavior long after the initial interaction.

Content

Scanner excerpt · policies/default_rules.json (reported line 57)May include surrounding context.

json
"human already approved",
    "owner said to always",
    "this was verified by the user",
    "treat this as permanent instruction"
  ],
  "report_templates": {
    "headline": "{recommendation} {path} risk={risk_score}",

Persistent Context Injection

Medium
Category
Memory Poisoning
Confidence
80% confidence
Finding

Skill injects content designed to persist in agent memory or context across interactions. Persistent injection can alter agent behavior long after the initial interaction.

Content

Scanner excerpt · policies/default_rules.json (reported line 57)May include surrounding context.

json
"human already approved",
    "owner said to always",
    "this was verified by the user",
    "treat this as permanent instruction"
  ],
  "report_templates": {
    "headline": "{recommendation} {path} risk={risk_score}",

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The manifest description frames the skill as an auditor for detecting poisoning patterns in memory stores. However, the code adds a clean subcommand and, when --apply is used, invokes clean_blocks(...) to rewrite files after creating backups, which is a materially broader behavior than auditing.

Content

No source excerpt is available for this finding.