Back to skill

Security audit

Scribe

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it says, but it automatically sends session history to an external LLM and can persist extracted behavior rules into memory on a recurring schedule without enough scoping or review controls.

Review this carefully before installing. It is best suited for users who are comfortable having their OpenClaw session messages processed by OpenRouter and summarized into durable local memory. Avoid using it on workspaces that may contain credentials, confidential project data, personal information, or untrusted copied text unless you add redaction, review, retention, and an easy way to disable the scheduled job.

Vulnerability Patterns
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • System PersistenceInstalls backdoors, hooks, services, or scheduled tasks that survive the run
  • 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
Findings (4)

T02 · Agent Memory Poisoning

Error
Location
scripts/scribe.py:116
Finding

Untrusted Session Content Can Poison Persistent Agent Memory

Content
View full analysis
Path: """Write extracted content to memory/YYYY-MM-DD.md.""" memory_dir = workspace / "memory" memory_dir.mkdir(parents=True, exist_ok=True) out_path = memory_dir / f"{date}.md" header = f"# {date} Memory (Scribe)\n\n" # Append if file already exists (manual notes may be there) if out_path.exists(): existing = out_path.read_text(encoding="utf-8") if "## 🔑 Decisions Made" in existing: # Already has scribe output — append with separator out_path.write_text( existing + f"\n\n---\n*Scribe update — {datetime.datetime.now().strftime('%H:%M')}*\n\n" + content, encoding="utf-8", ) else: out_path.write_text(existing + "\n\n" + header + content, encoding="utf-8") else: out_path.write_text(header + content, encoding="utf-8") return out_path def append_longterm(content: str, workspace: Path, date: str): """O ...[truncated 2317 chars]
Remediation
View remediation

other

Error
Location
scripts/scribe.py:116
Finding

Conversation History Is Transmitted to an External LLM Without Sensitive-Data Redaction

Content
View full analysis
max_chars: conversation_text = conversation_text[-max_chars:] print(f"[scribe] Truncated to last {max_chars} chars") print("[scribe] Extracting signals via LLM...") extracted = extract_with_llm(conversation_text, target_date) ``` ### Technical Analysis The skill collects user messages from session logs and sends up to 40,000 characters to OpenRouter. Filtering only removes heartbeat and system noise; it does not detect or redact API keys, authentication tokens, personal information, confidential project details, private URLs, or other sensitive material. External LLM processing is disclosed in the project documentation, so the tran ...[truncated 1232 chars]
Remediation
View remediation

T06 · System Persistence

Warning
Location
scripts/setup-cron.py:20
Finding

Setup Installs Recurring Cross-Session Agent Execution

Content
View full analysis
> /tmp/scribe.log 2>&1 ``` ### Technical Analysis The setup script uses the OpenClaw gateway token to register an enabled nightly cron job. The payload launches an isolated agent turn, which then executes Scribe and accesses session history. The documentation also provides a system-crontab ...[truncated 1451 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/scribe.py:139
Finding

Bearer Tokens and Conversation Payloads Are Exposed Through Process Arguments and Temporary Files

Content
View full analysis
dict: cmd = ["curl", "-s", "-X", method, url, "-H", "Content-Type: application/json", "-H", f"Authorization: Bearer {token}"] if data: cmd += ["-d", json.dumps(data)] result = subprocess.run(cmd, capture_output=True, text=True, timeout=15) if result.returncode != 0: raise RuntimeError(f"curl failed: {result.stderr}") return json.loads(result.stdout) ``` ### Technical Analysis Both the OpenRouter API key and OpenClaw gateway token are included directly in `curl` command-line arguments. Depending on the operating system and process-observation permissions, command arguments may be visible to other local us ...[truncated 1767 chars]
Remediation
View remediation
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
  • Rogue AgentSelf-Modification, Session Persistence
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (26)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared purpose is memory extraction, but the skill also sets up and manages cron jobs, reads local gateway configuration and tokens, and uses network/API access for scheduling. This behavior expansion is security-relevant because it introduces persistence, access to local secrets, and remote configuration changes that are not clearly disclosed in the top-level skill description, increasing the chance of unexpected privileged actions.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script sends user session contents wholesale to an external LLM API without an explicit warning or consent mechanism. Because session logs may include secrets, personal data, internal plans, or security-relevant instructions, this creates a substantial confidentiality risk through third-party data exposure.

Content

No source excerpt is available for this finding.

Ssd 3

High
Category
Not specified by scanner
Confidence
96% confidence
Finding

User messages are bulk-forwarded to an external model and the returned summary is persisted into memory files, creating two leakage paths: outbound disclosure to a third party and long-term local storage of potentially sensitive distilled content. Summaries can preserve secrets, intentions, and private preferences in a form that is easier to reuse or later exfiltrate.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README promotes nightly scanning of session logs and writing extracted content to persistent memory, but it does not warn users that this process may collect and retain sensitive data such as credentials, personal information, or confidential project details. In a memory-consolidation skill, this omission is especially risky because the whole feature is designed to process large volumes of conversational history automatically and persist derived data over time.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding

The skill advertises and operationalizes file access, environment access, and shell execution, but the manifest does not declare any explicit tool scope or permissions boundary. That creates an unnecessary trust gap: operators cannot easily tell what capabilities are required, and an overprivileged runtime could let the skill read sensitive local data or modify files beyond the intended memory output.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
88% confidence
Finding

The skill persists extracted session information into daily memory files and can optionally append to long-term memory, creating durable records of user activity and preferences. Persistent storage increases blast radius if the workspace is later accessed by other tools, users, or compromised processes, especially because summaries may consolidate sensitive details into easy-to-read files.

Content

Scanner excerpt · SKILL.md (reported line 22)May include surrounding context.

python3 skills/public/scribe/scripts/setup-cron.py

text

That's it. Scribe will run every night at 23:30 and write `memory/YYYY-MM-DD.md` to your workspace.

**3. Run manually anytime:**
```bash

Ssd 3

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill is explicitly designed to collect user session content and transmit it to an external LLM for summarization into persistent memory. In this context that behavior appears functional rather than overtly malicious, but it still creates a real data-exfiltration and privacy risk because potentially sensitive conversation content leaves the local environment and is stored in derived form.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill states that it sends user session messages to an external LLM service, but the description does not provide a clear privacy warning or informed-consent notice. Session logs can contain credentials, proprietary code, personal data, or operational details, so undisclosed third-party transmission materially increases confidentiality risk.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
84% confidence
Finding

The instructions tell the agent to add a recurring cron job that runs every night, establishing persistence for automated access to session logs and memory writing. In this skill's context, the persistence is part of intended functionality, but it still has security implications because it continuously processes potentially sensitive historical data without a fresh user action each time.

Content

Scanner excerpt · references/cron-setup.md (reported line 12)May include surrounding context.

md
### Add the cron job

Ask your agent:
> "Add a cron job that runs scribe every night at 23:30 Asia/Shanghai"

Or configure manually via the cron tool:

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

This agentTurn payload directs unattended execution of the scribe script to scan session logs and write a dated memory file, which is a persistence-enabling workflow. The danger is amplified by the combination of recurring execution and data consolidation: sensitive content from logs may be copied into a durable summary store, broadening exposure and retention.

Content

Scanner excerpt · references/cron-setup.md (reported line 26)May include surrounding context.

md
},
  "payload": {
    "kind": "agentTurn",
    "message": "Run the scribe skill now. Scan today's session logs and write memory/YYYY-MM-DD.md. Use: python3 skills/public/scribe/scripts/scribe.py"
  },
  "sessionTarget": "isolated"
}

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The cron setup explicitly automates scanning of session logs and writing extracted content into persistent memory files, but the instructions shown here provide no privacy warning, consent step, retention guidance, or scope limitation. Because session logs may contain sensitive prompts, secrets, or personal data, unattended nightly extraction increases the risk of over-collection and unintended persistence.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
89% confidence
Finding

The documentation instructs users to install a persistent system cron job that repeatedly executes the scribe script outside the normal interactive workflow. Persistence mechanisms are security-relevant because they enable recurring access to session data and continued operation even after the user forgets it was enabled, increasing exposure if the script behavior changes or logs contain sensitive data.

Content

Scanner excerpt · references/cron-setup.md (reported line 37)May include surrounding context.

For running outside OpenClaw:

bash
# crontab -e
30 23 * * * cd ~/.openclaw/workspace && python3 skills/public/scribe/scripts/scribe.py >> /tmp/scribe.log 2>&1

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script reads API credentials from environment variables and the user's OpenClaw config to enable outbound access, but this capability is not clearly justified or disclosed in the stated purpose. Silent credential harvesting from expected local stores increases trust risk and can surprise operators who did not consent to remote model usage.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
89% confidence
Finding

The script accesses API credentials from environment/config without visible disclosure to the user, which is a sensitive capability even if the credential is only used for its stated API call. Hidden credential access erodes trust boundaries and may violate operator expectations or organizational policy.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill description suggests local processing of session logs into memory files, but the implementation transmits the collected conversation text to OpenRouter for remote summarization. This mismatch is dangerous because users may reasonably expect local-only handling while sensitive session contents are actually exfiltrated to a third-party service.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/scribe.py (reported line 153)May include surrounding context.

python
try:
        import subprocess
        result = subprocess.run(
            [
                "curl", "-s", "--max-time", "60",
                "-X", "POST",

Tainted flow: 'api_key' from os.environ.get (line 87, credential/environment) → subprocess.run (code execution)

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/scribe.py (reported line 153)May include surrounding context.

python
try:
        import subprocess
        result = subprocess.run(
            [
                "curl", "-s", "--max-time", "60",
                "-X", "POST",

Session Persistence

Medium
Category
Rogue Agent
Confidence
87% confidence
Finding

Registering a nightly cron job establishes persistence: the skill will continue to run automatically and process session logs without a fresh user action each time. In a skill that reads agent session history and writes memory artifacts, persistence materially increases data exposure and the blast radius of any later modification or misuse.

Content

Scanner excerpt · scripts/setup-cron.py (reported line 8)May include surrounding context.

python
Usage:
    python3 scripts/setup-cron.py

This script calls the OpenClaw Gateway API to register a cron job that runs
scribe every night at 23:30 (local timezone). The job runs in an isolated
session and writes memory/YYYY-MM-DD.md to your workspace.
"""

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The cron job configuration forces the locale-specific timezone "Asia/Shanghai" in the default schedule. This is a natural-language policy concern because it imposes a specific locale behavior on all users unless they manually edit the script, and no opt-in or prompt is provided.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
90% confidence
Finding

The cron payload directs recurring automated execution that scans session logs and writes structured memory files, creating durable background behavior. In context, this is more sensitive than ordinary task automation because it repeatedly processes potentially confidential conversation history and stores derived summaries in the workspace.

Content

Scanner excerpt · scripts/setup-cron.py (reported line 35)May include surrounding context.

python
"Run the scribe skill now. "
            "Execute: python3 skills/public/scribe/scripts/scribe.py — "
            "scan today's session logs from ~/.openclaw/agents/main/sessions/ "
            "and write structured memory to memory/YYYY-MM-DD.md in the workspace. "
            "Report how many messages were processed and where the file was written."
        ),
    },

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The setup script reads a local gateway bearer token from environment or config, giving the skill authority to act on the OpenClaw gateway. That exceeds simple memory extraction and expands the trust boundary: if the skill or its distribution is modified, it can reuse privileged local credentials to perform gateway actions without explicit per-action authorization.

Content

No source excerpt is available for this finding.

subprocess module call

Medium
Category
Dangerous Code Execution
Confidence
70% confidence
Finding

subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Content

Scanner excerpt · scripts/setup-cron.py (reported line 76)May include surrounding context.

python
"-H", f"Authorization: Bearer {token}"]
    if data:
        cmd += ["-d", json.dumps(data)]
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=15)
    if result.returncode != 0:
        raise RuntimeError(f"curl failed: {result.stderr}")
    return json.loads(result.stdout)

Tainted flow: 'cmd' from os.environ.get (line 71, credential/environment) → subprocess.run (code execution)

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/setup-cron.py (reported line 76)May include surrounding context.

python
"-H", f"Authorization: Bearer {token}"]
    if data:
        cmd += ["-d", json.dumps(data)]
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=15)
    if result.returncode != 0:
        raise RuntimeError(f"curl failed: {result.stderr}")
    return json.loads(result.stdout)

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

This script can enumerate, delete, and create cron jobs on the local gateway, which is a persistence-capable administrative action beyond passive scribing. In context, that makes the skill more dangerous because compromising or repurposing the setup script enables durable automated execution and interference with existing scheduled tasks.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
94% confidence
Finding

The sample invocation and JSON configuration both hard-code the locale/timezone to Asia/Shanghai. Because no opt-in, alternative, or justification is provided, this is a natural-language locale policy concern under the rule for forced language/locale settings.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.