Back to skill

Security audit

config-guardian

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its config-protection purpose, but a persistent root service sends alerts to hard-coded Discord and Telegram recipients and has security-relevant implementation weaknesses.

Review this carefully before installing. Only install if you are comfortable running a persistent root service that can automatically overwrite openclaw.json, signal a gateway process, and send security-event details through your OpenClaw messaging setup to the package's hard-coded Discord and Telegram targets. Prefer editing the script first to disable or administrator-configure external alerts, and fix validation to trust the validator exit status rather than the text "Config valid".

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 (3)

other

Warning
Location
scripts/openclaw-config-guardian.sh:71
Finding
Security alerts are sent to hard-coded external recipients<![CDATA[ ## Vulnerability Details **File Location**: `scripts/openclaw-config-guardian.sh`, lines 71–75 **Vulnerability Type**: Hard-coded external data destination **Risk Level**: Medium ### Vulnerable Code ```bash send_alert() { local msg="$1" openclaw message send --channel discord --channel-id 1483995509910667455 "$msg" 2>/dev/null || true openclaw message send --channel telegram --target telegram:5189839048 "$msg" 2>/dev/null || true } ``` ### Technical Analysis The root-level guardian sends security alerts to fixed Discord and Telegram recipient identifiers. These destinations are embedded by the package author rather than selected or approved by the installing operator. The behavior is disclosed generally in the documentation, but the code does not request consent, validate recipient ownership, or provide a configuration mechanism. Alerts can contain operational details such as integrity-check failures, local filesystem paths, timestamps, snapshot paths, lock status, and validation-failure events. Although the guardian does not open network connections directly, invoking `openclaw message send` causes the local OpenClaw infrastructure to transmit the information externally. Delegating transmission to another local component does not eliminate the data-disclosure risk. ### Attack Path 1. An administrator installs and enables the guardian without changing its source. 2. The service runs as root and monitors `/root/.openclaw/openclaw.json`. 3. An integrity failure occurs, or three configuration-validation failures trigger lock mode. 4. `send_alert` invokes the OpenClaw messaging CLI. 5. The alert is sent to the hard-coded Discord and Telegram recipients. 6. Whoever controls those destinations receives the disclosed host security and operational information. No attacker gains local privileges directly through this issue. The security consequence is unauthorized external disclosure and use of the operator's configured messaging infrastructure ...[truncated 567 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove all default Discord and Telegram recipient identifiers from the packaged script. 2. Make external notifications disabled by default. 3. Require the administrator to explicitly configure each destination through a root-owned configuration file, such as: ```ini ALERTS_ENABLED=false DISCORD_CHANNEL_ID= TELEGRAM_TARGET= ``` 4. Set configuration ownership to `root:root` and permissions to `0600`. 5. Validate destination syntax before invoking the messaging CLI. 6. Document the exact data included in each notification and require explicit opt-in during installation. 7. Minimize notification contents by excluding local paths, snapshot names, and other unnecessary host details. 8. Consider local journald alerts as the secure default, with external messaging offered only as an optional integration. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/openclaw-config-guardian.sh:205
Finding
Configuration validation trusts a text substring and discards the validator exit status<![CDATA[ ## Vulnerability Details **File Location**: `scripts/openclaw-config-guardian.sh`, lines 205–213 **Vulnerability Type**: Improper validation-result handling **Risk Level**: Medium ### Vulnerable Code ```bash validate_config() { local out out=$(openclaw config validate 2>&1) || true if echo "$out" | grep -q "Config valid"; then return 0 fi log "❌ validate failed: $out" return 1 } ``` ### Technical Analysis The function explicitly suppresses a nonzero exit status from `openclaw config validate` by appending `|| true`. It then treats any combined standard output or error output containing the substring `Config valid` as successful validation. This is weaker than checking the validator's actual exit status or parsing a structured result. Output such as the following would incorrectly satisfy the check: ```text Config validation error: previous Config valid state could not be loaded ``` If validator error messages reflect attacker-controlled configuration values, a crafted value containing `Config valid` may also cause a false-positive result. Exploitability through reflected values depends on the behavior of the installed OpenClaw validator, but the incorrect result-handling logic itself is present. On a false positive, `after_success` updates `baseline.bak` from the untrusted current configuration. This destroys the expected distinction between the current candidate and the last known-good rollback source. ### Attack Path 1. An actor able to modify `/root/.openclaw/openclaw.json` writes an invalid configuration. 2. The guardian detects the write and invokes `openclaw config validate`. 3. The validator exits unsuccessfully but emits output containing the exact substring `Config valid`. 4. `|| true` discards the unsuccessful exit status. 5. `grep -q "Config valid"` returns success. 6. The guardian calls `after_success`. 7. The invalid configuration is copied into `baseline.bak`, the failure counter is reset, and the gateway recei ...[truncated 1020 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Preserve and require the validator's successful exit status: ```bash validate_config() { local out if out=$(/absolute/path/to/openclaw config validate 2>&1); then log "✅ validation succeeded" return 0 fi log "❌ validate failed: $out" return 1 } ``` 2. Use an absolute, administrator-verified path to the OpenClaw executable. 3. If OpenClaw supports machine-readable output, request JSON and verify an explicit boolean or status field with `jq`. 4. Do not infer security decisions from human-readable output substrings. 5. Validate the initial configuration before creating the first baseline. The current implementation copies the initial file without first proving it is valid. 6. Write a new baseline to a temporary file in the same root-owned directory, verify it, and atomically rename it into place. 7. Add regression tests for: - Nonzero exit status with output containing `Config valid`. - Localized or changed validator messages. - Invalid configuration values containing the accepted phrase. - Empty output and interrupted validation. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/openclaw-config-guardian.sh:216
Finding
Broad process matching can cause the root service to signal an unrelated process<![CDATA[ ## Vulnerability Details **File Location**: `scripts/openclaw-config-guardian.sh`, lines 216–228 **Vulnerability Type**: Unsafe privileged process selection **Risk Level**: Low ### Vulnerable Code ```bash reload_gateway() { local gw_pid gw_pid=$(pgrep -f "$GATEWAY_PID_PATTERN" 2>/dev/null | head -1 || true) if [[ -n "$gw_pid" ]]; then kill -SIGUSR1 "$gw_pid" 2>/dev/null \ && log "📡 SIGUSR1 sent to gateway (pid=$gw_pid)" \ || log "⚠️ failed to send SIGUSR1 to gateway (pid=$gw_pid)" audit "GATEWAY_RELOAD" "SIGUSR1 -> pid=$gw_pid" else log "⚠️ gateway process not found, skipping reload signal" audit "GATEWAY_RELOAD" "skipped: no gateway process" fi } ``` The matching pattern is defined as: ```bash GATEWAY_PID_PATTERN='openclaw-gateway' ``` ### Technical Analysis `pgrep -f` searches the complete command line of every accessible process. It does not verify the executable path, process owner, systemd unit, or whether the selected process is actually the OpenClaw gateway. The code then selects only the first match with `head -1`. Because the guardian runs as root, the subsequent `kill -SIGUSR1` is not constrained to processes owned by an unprivileged service account. Any process whose command line contains `openclaw-gateway` can potentially be selected. The effect of `SIGUSR1` is application-dependent. A process may reload state, execute a custom signal handler, ignore the signal, or terminate if it has no suitable handler. ### Attack Path 1. A local process is launched with `openclaw-gateway` in its command line, or an unrelated legitimate process already contains that text. 2. The process becomes the first result returned by `pgrep -f`. This may be easier when the real gateway is stopped or during a gateway restart. 3. A valid configuration write, rollback, or manual unlock invokes `reload_gateway`. 4. The root guardian selects the unrelated PID. 5. The guardian sends `SIGUSR1` to that process with root aut ...[truncated 816 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Address the gateway through its exact systemd unit rather than searching process command lines: ```bash systemctl kill --kill-who=main --signal=SIGUSR1 openclaw-gateway.service ``` 2. Alternatively, obtain the unit's main PID: ```bash gw_pid=$(systemctl show --property MainPID --value openclaw-gateway.service) ``` 3. Before signaling a numeric PID: - Reject empty values, zero, PID 1, and the guardian's own PID. - Verify `/proc/$pid/exe` against the expected executable. - Verify the process belongs to the expected systemd cgroup. - Verify the expected process owner. 4. Log and abort if identity checks fail; do not fall back to broad `pgrep -f` matching. 5. Use a dedicated gateway reload API or OpenClaw command if one provides authenticated and identity-safe reload behavior. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (25)

Chaining Abuse

High
Category
Tool Misuse
Content
local ts
    ts=$(date +%Y%m%d_%H%M%S)
    cp "$BASELINE" "$BASELINE_HISTORY_DIR/baseline_${ts}.bak"
    ( cd "$BASELINE_HISTORY_DIR" && ls -t baseline_*.bak 2>/dev/null | tail -n +$((BASELINE_KEEP + 1)) | xargs -r rm -f ) || true
    log "📦 baseline archived (history kept: $BASELINE_KEEP versions)"
  fi
  cp "$CONFIG_FILE" "$BASELINE"
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Chaining Abuse

High
Category
Tool Misuse
Content
local ts
    ts=$(date +%Y%m%d_%H%M%S)
    cp "$BASELINE" "$BASELINE_HISTORY_DIR/baseline_${ts}.bak"
    ( cd "$BASELINE_HISTORY_DIR" && ls -t baseline_*.bak 2>/dev/null | tail -n +$((BASELINE_KEEP + 1)) | xargs -r rm -f ) || true
    log "📦 baseline archived (history kept: $BASELINE_KEEP versions)"
  fi
  cp "$CONFIG_FILE" "$BASELINE"
Confidence
75% confidence
Finding
Tool calls are chained to bypass individual safety checks or escalate capabilities beyond what any single tool call would allow.

Lp3

Medium
Category
MCP Least Privilege
Confidence
70% confidence
Finding
Without declared permissions the skill's intent is opaque and cannot be validated.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The skill's natural-language instructions from the title onward are presented only in Chinese, which effectively forces a specific language on users. The policy allows locale constraints when clearly justified or optional, but this file does not provide an opt-in or explain that the skill is intentionally region-specific.

Description-Behavior Mismatch

Medium
Confidence
92% confidence
Finding
The design adds automatic dual-channel Discord and Telegram alerting to a skill whose core purpose is local configuration integrity protection. That creates an unnecessary outbound communications path from a root-running guardian process, increasing the attack surface and risking leakage of configuration details, errors, paths, or operational state to external services.

Context-Inappropriate Capability

Medium
Confidence
95% confidence
Finding
Automatic messaging to Discord and Telegram is outside the minimum privileges needed for config rollback and validation, especially in a component running as root. Even if intended for alerting, it can exfiltrate environment details or be abused as an unexpected outbound channel, making the skill more dangerous than its local-protection description suggests.

Context-Inappropriate Capability

Medium
Confidence
90% confidence
Finding
The manifest specifically mentions a `SIGUSR1` gateway hot-reload, which is a narrower and safer action than full service restart. The design's extension to automatically run `openclaw gateway restart` would add a stronger operational control capability that is not justified by the stated purpose and directly exceeds the described mechanism.

Session Persistence

Medium
Category
Rogue Agent
Content
```bash
systemctl daemon-reload
systemctl enable --now openclaw-config-guardian
systemctl status openclaw-config-guardian
# 应显示:active (running)
# 日志应显示:🛡️ guardian v3 started
Confidence
80% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
```bash
systemctl daemon-reload
systemctl enable --now openclaw-config-guardian
systemctl status openclaw-config-guardian
# 应显示:active (running)
# 日志应显示:🛡️ guardian v3 started
Confidence
80% 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.

Session Persistence

Medium
Category
Rogue Agent
Content
```bash
systemctl daemon-reload
systemctl enable --now openclaw-config-guardian
systemctl status openclaw-config-guardian
# 应显示:active (running)
# 日志应显示:🛡️ guardian v3 started
Confidence
80% 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.

Description-Behavior Mismatch

Medium
Confidence
94% confidence
Finding
The documentation states that the guardian sends Discord and Telegram alerts on circuit-break events, but this notification capability is not part of the stated skill purpose of local config protection and recovery. Undocumented external messaging expands the trust boundary, may exfiltrate operational state to third-party services, and creates hidden behavior administrators may not review or authorize.

Context-Inappropriate Capability

Medium
Confidence
91% confidence
Finding
Discord and Telegram alerting is not inherently necessary for a config rollback guardian, so its presence suggests unnecessary external communications capability. If implemented, it could leak sensitive operational details, introduce secrets management risk, and widen the attack surface beyond the core responsibility of protecting openclaw.json.

Missing User Warnings

Medium
Confidence
88% confidence
Finding
This markdown file instructs users to run `find ... -delete` to remove backup snapshots, but the surrounding text does not explicitly warn that files older than 30 days will be permanently deleted. For markdown files, SQP-2 applies when descriptions omit warnings about behaviors that can affect user data or system integrity.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The script exfiltrates operational/security event data to hardcoded Discord and Telegram destinations, which goes beyond local config protection and creates an unnecessary outbound data path. Even if only alerts are sent, messages may disclose filesystem paths, failure states, timestamps, and security incidents to third parties without clear authorization or minimization.

Context-Inappropriate Capability

Medium
Confidence
93% confidence
Finding
Hardcoded remote messaging capability is not necessary to enforce rollback or validation of a local config file and expands the attack surface. In a root-run guardian script, this creates a covert notification/exfiltration channel that could leak sensitive operational context whenever failures or integrity issues occur.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The script sends alert data over the network without clear user disclosure or consent, which can expose internal security events and configuration health details externally. In a local protection skill, undisclosed outbound communications are especially concerning because they violate least surprise and may breach privacy or policy requirements.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The script overwrites the live configuration file by copying the baseline back into place, which is a safety-critical file write that can discard recent changes. While the script logs internally, there is no direct user confirmation before rollback and no nearby comment or user-facing disclosure warning that active config changes may be automatically reverted.

Natural-Language Policy Violations

Low
Confidence
93% confidence
Finding
This markdown file presents all operational and archival information only in Chinese, including headings, notes, and deployment status. Under the stated policy, forcing a specific language without user opt-in can be a natural-language policy violation unless the locale limitation is clearly justified.

Natural-Language Policy Violations

Low
Confidence
80% confidence
Finding
该技能文档从标题开始即完全以中文编写,且未提供语言选择、双语说明或适用语言范围说明。按规则,若技能强制特定语言而无用户 opt-in,可视为自然语言层面的语言/区域策略问题。

Context-Inappropriate Capability

Low
Confidence
80% confidence
Finding
The extension suggestion to run `git add/commit` introduces repository mutation and version-control side effects beyond validation, rollback, and audit of `openclaw.json`. That capability is not necessary to fulfill the stated manifest purpose and would broaden the skill into source-control automation.

Context-Inappropriate Capability

Low
Confidence
84% confidence
Finding
Calling external APIs for Slack or Discord notifications adds network communication behavior unrelated to the core need to validate and recover `openclaw.json`. Since the manifest does not describe webhook or API usage, this capability is not justified by the stated purpose.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The file consistently presents operational instructions in Chinese only, including headings, warnings, and procedures. Under SQP-3, forcing a specific language without user opt-in or a documented justification is a natural-language policy concern.

Natural-Language Policy Violations

Low
Confidence
97% confidence
Finding
The alert strings are written in Chinese and do not indicate any language choice, fallback, or user opt-in. This can violate language or locale policy where skills should not force a specific language unless explicitly justified or configurable.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
This critical alert message is hardcoded in Chinese with no evidence of locale selection or opt-in. As written, the skill's natural-language output enforces one language for notifications regardless of operator preference.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
The circuit-breaker alert text is delivered in Chinese only and does not provide a configurable locale or user opt-in. This is a natural-language policy concern because the skill dictates operator-facing language unconditionally.

Static analysis

No suspicious patterns detected.