Back to skill

Security audit

openclaw-audit-watchdog

Security checks for vulnerabilities and agentic risk

Overview

This skill is mostly coherent, but it installs a persistent external-reporting audit job and has report-integrity and transport risks users should review before installing.

Install only if you intend to create an unattended recurring OpenClaw audit job that sends reports to the configured DM target and optional email recipient. Review the cron payload, recipients, SMTP settings, install directory permissions, and PROMPTSEC_GIT_PULL before enabling it; prefer local sendmail or TLS-protected mail handling, keep git auto-pull disabled unless you have a verified release process, and verify deep-audit results independently until the report omission bug is fixed.

Vulnerability Patterns
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • 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
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
Findings (5)

T06 · System Persistence

Error
Location
scripts/setup_cron.mjs:287
Finding

Unattended Cross-Session Persistence Through a Recurring OpenClaw Cron Job

Content
View full analysis
Remediation
View remediation

T03 · Remote Payload Retrieval and Execution

Error
Location
scripts/runner.sh:31
Finding

Mutable Git Content Can Be Retrieved and Executed by the Persistent Runner

Content
View full analysis
/dev/null 2>&1 && [[ -d "$ROOT_DIR/.git" ]]; then git -C "$ROOT_DIR" pull --ff-only >/dev/null 2>&1 || true fi fi args=( ) if [[ -n "$HOST_LABEL" ]]; then args+=(--label "$HOST_LABEL") fi if [[ "$ENABLE_SUPPRESSIONS" -eq 1 ]]; then args+=(--enable-suppressions) fi if [[ -n "$AUDIT_CONFIG" ]]; then args+=(--config "$AUDIT_CONFIG") fi REPORT="$($SCRIPT_DIR/run_audit_and_format.sh "${args[@]}")" ``` ### Technical Analysis When `PROMPTSEC_GIT_PULL=1`, the runner performs `git pull --ff-only` against the repository's currently configured remote. The code does not verify: - The expected remote URL. - The fetched commit hash. - A signed commit or signed tag. - A release manifest or artifact checksum. - Whether executable files changed during the pull. A fast-forward-only pull prevents local history rewriting but does not establish authenticity. A malicious commit can still be fast-forwarded from a compromised or redirected remote. Immediately afterward, the runner executes `run_audit_and_format.sh` from the same mutable working tree. The pull failure is also ignored with `|| true`, preventing operators from reliably distinguishing a verified update from an update failure. ### Attack Path 1. The operator enables `PROMPTSEC_GIT_PULL=1`, and the value is optionally persisted in the cron payload. 2. An attacker compromises the configured Git repository, an authorized maintainer account, or the local repository's remote configuration. 3. The attacker publishes a fast-forward commit that modifies `run_audit_and_format.sh`, `render_report.mjs`, or another executable helper. 4. The recurring runner performs `git pull --ff-only` and accepts the malicious commit without authenticity verification ...[truncated 662 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
scripts/render_report.mjs:137
Finding

Deep-Audit Critical and Warning Findings Are Omitted from the Main Report

Content
View full analysis
25) lines.push(`…${deduped.length - 25} more`); } // Surface deep probe failure if present const deepProbe = Array.isArray(deep?.findings) ? deep.findings.find((f) => f?.checkId === "gateway.probe_failed") : null; ``` ### Technical Analysis The renderer computes both standard and deep findings but selects `a.summary` whenever that object is present. Because an empty summary object is truthy in JavaScript, deep-audit counts are not combined with standard-audit counts. The main findings list is populated only from: ```js top.push(...a.critical, ...a.warn); ``` Consequently, critical and warning findings found only by the deep audit do not appear in the main findings section. The only deep finding handled separately is the special `gateway.probe_failed` finding. This is particularly significant because the Skill advertises de ...[truncated 1210 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/send_smtp.mjs:34
Finding

SMTP Fallback Transmits Security Audit Reports Without TLS or Authentication

Content
View full analysis
new Promise((resolve, reject) => { const onData = (chunk) => { buffer += chunk.toString("utf8"); const idx = buffer.indexOf("\r\n"); if (idx !== -1) { const line = buffer.slice(0, idx); buffer = buffer.slice(idx + 2); cleanup(); resolve(line); } }; const onError = (e) => { cleanup(); reject(e); }; const onTimeout = () => { cleanup(); reject(new Error("SMTP timeout")); }; const cleanup = () => { socket.off("data", onData); socket.off("error", onError); socket.off("timeout", onTimeout); }; socket.on("data", onData); socket.on("error", onError); socket.on("timeout", onTimeout); }); const write = (line) => socket.write(line + "\r\n"); try { const greet = await readLine(); expectCode(greet, ["220"]); write(`EHLO ${helo}`); // Consume EHLO multi-line: 250-..., then 250 ... while (true) { const l = aw ...[truncated 2249 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Note
Location
scripts/run_audit_and_format.sh:63
Finding

Audit Error Output Is Embedded into JSON Without Escaping

Content
View full analysis
"$outfile" 2>"$errfile"; then printf '{"findings":[],"summary":{"critical":0,"warn":0,"info":0},"error":"audit failed: %s"}\n' \ "$(head -n 20 "$errfile" | tr '\n' ' ')" >"$outfile" fi else if ! openclaw security audit --deep --json "${config_args[@]}" >"$outfile" 2>"$errfile"; then printf '{"findings":[],"summary":{"critical":0,"warn":0,"info":0},"error":"deep failed: %s"}\n' \ "$(head -n 20 "$errfile" | tr '\n' ' ')" >"$outfile" fi fi ``` ### Technical Analysis The script inserts the first 20 stderr lines directly into a quoted JSON string. Replacing newlines with spaces does not escape other JSON-significant characters, including double quotes, backslashes, tabs, carriage returns, or additional control characters. For example, stderr containing: ```text failed to parse "config.json" ``` produces syntactically invalid JSON because the embedded quotation marks terminate the `error` string. The renderer then reports a generic parse failure rather than the original audit error. If an attacker can influence audit stderr through a malicious scanned artifact, configuration value, plugin, or compromised OpenClaw executable, the attacker can reliably disrupt report parsing. This is primarily a monitoring availability and diagnostic-integrity problem; the malformed JSON is parsed with `JSON.parse` and is not evaluated as code. ### Attack Path 1. The standard or deep audit command fails. 2. Its stderr contains an unescaped quotation mark, backslash, tab, or control character. 3. The shell interpolates that stderr into the JSON template. 4. The resulting audit file is malformed. 5. `render_report.mjs` fails to parse the file ...[truncated 518 chars]
Remediation
View remediation
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • System Prompt LeakageDirect Leakage, Indirect Extraction, Tool-Based Exfiltration
  • Rogue AgentSelf-Modification, Session Persistence
Findings (15)

Tp4

High
Category
MCP Tool Poisoning
Confidence
99% confidence
Finding

The declared description centers on an automation workflow: recurring daily audits of OpenClaw agents, cron setup/maintenance, and report distribution through DM/email. The actual code chunk instead only invokes the Codex CLI in read-only review mode against the local skill directory. Its purpose is code review of the skill itself, not operational audits of agents. There is no evidence of scheduling, cron manipulation, messaging, email sending, recipient configuration, or recurring execution. This is a material purpose and capability mismatch, not merely an implementation detail difference.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The code chunk is a local wrapper script that executes openclaw security audit and openclaw security audit --deep, then invokes render_report.mjs to format the results. Its behavior is limited to producing a formatted report on stdout. There is no logic for creating, updating, or interacting with cron; no messaging, DM, email, SMTP, webhook, or recipient-delivery functionality; and no trigger or scheduling mechanism indicating daily automated runs. The security audit/report formatting portion matches part of the description, but the declared purpose significantly overstates automation and delivery capabilities not present in this code.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
90% confidence
Finding

The core auditing and reporting behavior generally aligns with the description: the script runs the audit workflow, formats output, prints to stdout for cron-driven delivery, and optionally emails reports. However, the declared purpose explicitly says it creates or updates a recurring cron job, and this code does not do any scheduling or cron management at all. Additionally, the script includes an undeclared capability to run git pull on the repository when enabled via environment variable. That extra behavior changes repository state and is not described. Because the cron-management claim is materially unsupported and there is an extra undeclared repo-update capability, this is a mismatch.

Content

No source excerpt is available for this finding.

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding

The declared description presents a full daily security audit system with scheduling, report generation, DM delivery, and optional email reporting. The supplied code chunk is much narrower: it is a helper script that formats and sends an email through sendmail. While email reporting is consistent with one part of the description, the script does not implement the primary declared behavior of running audits or managing cron jobs, nor does it handle DM delivery. Therefore the description materially overstates what this code chunk actually does.

Content

No source excerpt is available for this finding.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
For standalone installs, verify the signed release manifest before trusting `SKILL.md`, `skill.json`, or the archive. The `skill.json` file is the package metad

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
For standalone installs, verify the signed release manifest before trusting `SKILL.md`, `skill.json`, or the archive. The `skill.json` file is the package metad

External Script Fetching

High
Category
Supply Chain
Confidence
90% confidence
Finding

The skill includes a standalone installation flow that downloads multiple artifacts from the network. Although it performs stronger-than-average signature and checksum verification, it still conditions trust on remote retrieval of the public key and release assets, which expands supply-chain risk; if users skip verification steps or the process is modified, malicious content could be installed and later persisted via cron.

Content

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

md
RELEASE_PUBKEY_SHA256="711424e4535f84093fefb024cd1ca4ec87439e53907b305b79a631d5befba9c8"

curl -fsSL "$BASE/checksums.json" -o "$TMP_DIR/checksums.json"
curl -fsSL "$BASE/checksums.sig" -o "$TMP_DIR/checksums.sig"
curl -fsSL "$BASE/signing-public.pem" -o "$TMP_DIR/signing-public.pem"
curl -fsSL "$BASE/$ZIP_NAME" -o "$TMP_DIR/$ZIP_NAME"

External Model or Provider Selection

High
Category
Excessive Agency
Confidence
90% confidence
Finding

Skill selects an external model or provider that may use a different account or billing plan than the operator expects. Undisclosed model switches can cause unexpected cost or quota consumption.

Content

Scanner excerpt · scripts/codex_review.sh (reported line 22)May include surrounding context.

sh
# Use GPT-5.1 Codex Max (high reasoning). Note: some models (e.g. o3) may be blocked
# depending on the account type.
exec "$RESOLVED_CODEX_BIN" review -s read-only -m gpt-5.1-codex-max \
  "Review this skill for security/reliability issues. Focus on: shell quoting, command injection, sendmail header injection, dependency checks, cron payload safety, and failure modes. Provide concrete patch suggestions (with diffs if possible)." \
  -c "workdir=\"$ROOT_DIR\"" \
  -c "reasoning_effort=\"xhigh\""

Direct Prompt Extraction

High
Category
System Prompt Leakage
Confidence
85% confidence
Finding

Skill contains instructions that could directly expose system prompts, internal rules, or hidden instructions to users or external parties.

Content

Scanner excerpt · scripts/render_report.mjs (reported line 96)May include surrounding context.

js
// Check if this finding matches any suppression rule
    const isSuppressed = suppressions.some((rule) => {
      return rule.checkId === checkId && normalizeSkillName(rule.skill) === normalizedSkillName;
    });

    if (isSuppressed) {

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

bash
# Install skill
mkdir -p ~/.openclaw/skills/openclaw-audit-watchdog
cd ~/.openclaw/skills/openclaw-audit-watchdog

# Download and extract

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding

The skill declares required environment variables and operational behaviors but does not define an explicit tool scope such as permissions or allowed-tools. For a skill that persists a cron job, sends messages, and may perform email delivery, missing tool scoping weakens least-privilege controls and can allow broader-than-necessary capability use at runtime.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
93% confidence
Finding

The skill explicitly creates or updates an unattended recurring cron job, which introduces persistence on the host. Even for a legitimate security tool, persistence increases risk because a misconfigured payload, compromised skill, or later environment change can cause repeated execution and repeated data exfiltration of audit results to external DM/email targets.

Content

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

md
## Goal

Create (or update) a daily cron job that:

1) Runs:
- `openclaw security audit --json`

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
80% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

md
→ Remediation: Run `openclaw security audit --fix` to update

[WARN-007] Weak Permission on Config File
→ Remediation: chmod 600 ~/.openclaw/config.json

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Run `openclaw security audit --deep` for full details.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · examples/README.md (reported line 59)May include surrounding context.

  1. Copy the example config:
bash
mkdir -p ~/.openclaw
cp security-audit-config.example.json ~/.openclaw/security-audit.json

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The trigger list includes generic phrases such as "security audit", "run audit", and "security report" that can match routine user requests not specifically intended for this skill. In a skill system where triggers influence automatic selection, overly broad activation can cause unintended execution of a persistent, externally reporting audit workflow, increasing the chance of surprise cron installation or report delivery.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.