Back to skill

Security audit

Gateway Auto-Rollback

Security checks for vulnerabilities and agentic risk

Overview

The skill is meant to protect OpenClaw Gateway configs, but its rollback safety claims are stronger than the implementation and some instructions can overwrite or expose sensitive config files.

Review this carefully before installing. It touches important OpenClaw Gateway configuration, approval, and skill registry files, but the automatic rollback path may not actually recover the last good config after a bad change. Avoid running the test script as a privileged user, inspect backups before restoring them, and use a private temporary directory and a stronger health check if adapting this skill.

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)

T09 · Insecure Skill Coding Practices

Error
Location
gateway-auto-rollback.py:158
Finding
Watch mode restores the already-modified configuration instead of a known-good backup## Vulnerability Details **File Location**: `gateway-auto-rollback.py`, lines 158-164; related rollback logic at lines 84-94 **Vulnerability Type**: Incorrect backup sequencing and ineffective rollback **Risk Level**: High ### Vulnerable Code ```python if new_hash != old_hash: log_event("WARN", f"⚠️ 检测到修改: {file_path.name}") change_detected = True consecutive_healthy = 0 backup = create_backup(file_path) if not post_modification_verify(file_path, backup): log_event("ERROR", "修改验证失败,已回滚") ``` The resulting backup is subsequently restored using: ```python config_file = CONFIG_DIR / backup_path.name.split(".")[0] try: shutil.copy2(backup_path, config_file) ``` ### Technical Analysis Watch mode detects a modification by comparing the current file hash with a previously recorded hash. This comparison necessarily occurs after the configuration file has already been changed. Once a difference is detected, the watcher calls `create_backup(file_path)`. The backup therefore contains the new, potentially malformed or service-breaking configuration rather than the previous known-good content. If JSON or Gateway validation subsequently fails, `post_modification_verify()` passes this newly created backup to `rollback_to_backup()`, which copies the same changed content back over the configuration file. The old hash cannot support recovery because it only identifies the previous content and does not preserve that content. Consequently, the documented automatic rollback protection is ineffective in watch mode. ### Attack Path 1. An attacker or faulty automation with permission to modify a monitored configuration changes `openclaw.json`, `exec-approvals.json`, or `skills.json`. 2. The watcher observes that the current hash differs from its stored hash. 3. The watcher creates a backup from the already-modified file. 4. The changed configuration fails JSON validation or causes the G ...[truncated 843 chars]
Remediation
## Remediation Suggestions - Preserve a known-good snapshot before any modification occurs. Watch mode should maintain an actual copy of the last validated content, not only its hash. - When a change is detected, validate the current file before replacing the known-good snapshot. - If validation fails, restore the previously retained known-good snapshot. - Update the known-good snapshot and stored hash only after JSON validation and Gateway health validation both succeed. - Use atomic operations: write backups to a temporary file, flush them, and atomically rename them into place. - Reject a missing or invalid backup path before attempting rollback. - After restoration, recalculate the active file hash and repeat JSON and Gateway validation to confirm that rollback succeeded. - Add an integration test that writes an invalid configuration, invokes the watcher flow, and verifies byte-for-byte restoration of the original file.

T09 · Insecure Skill Coding Practices

Warning
Location
gateway-auto-rollback.py:74
Finding
Gateway health check accepts HTTP error responses as healthy## Vulnerability Details **File Location**: `gateway-auto-rollback.py`, lines 74-81 **Vulnerability Type**: Improper HTTP response validation **Risk Level**: Medium ### Vulnerable Code ```python try: result = subprocess.run( ["curl", "-s", "http://127.0.0.1:18789/api/health"], timeout=3, capture_output=True ) return result.returncode == 0 except: return False ``` ### Technical Analysis The implementation treats a zero `curl` process exit status as proof that the Gateway is healthy. By default, `curl` can exit successfully after receiving HTTP error responses such as 401, 404, or 500. The `-s` option only suppresses output; it does not cause HTTP failure status codes to produce a nonzero exit status. The function also does not inspect the HTTP status code, response headers, content type, or response body. As a result, any reachable local HTTP service can satisfy the check even when the requested health endpoint reports an error or returns an unrelated payload. Because this function controls post-modification acceptance and the watcher's healthy-check counter, false-positive results can prevent rollback and cause monitoring to terminate prematurely. ### Attack Path 1. A configuration modification leaves the Gateway unhealthy, or another local service responds on port 18789. 2. The endpoint returns an HTTP error or arbitrary response while completing the TCP and HTTP exchange. 3. `curl` exits with status zero because it was not invoked with an HTTP-failure option. 4. `check_gateway_health()` returns `True`. 5. The modified configuration is accepted as valid, or the watcher increments its consecutive healthy counter. 6. After three false-positive checks, watch mode may terminate while the Gateway remains unhealthy. ### Impact Assessment This issue does not directly grant system privileges. Its primary impact is integrity and availability: invalid configuration c ...[truncated 316 chars]
Remediation
## Remediation Suggestions - Invoke curl with `--fail --silent --show-error` so HTTP 4xx and 5xx responses fail the check. - Explicitly require the expected HTTP status, normally 200. - Parse the response body and verify the Gateway's documented health schema and healthy-state value. - Prefer Python's standard HTTP libraries to avoid dependence on an external executable and to inspect status and body directly. - Catch specific exceptions instead of using a bare `except`, and log the failure reason without exposing sensitive response data. - If the health endpoint requires authentication, use an appropriately protected credential and verify that unauthorized responses cannot pass. - Add tests for HTTP 200 with a healthy body, HTTP 200 with an unhealthy body, HTTP 401, HTTP 404, HTTP 500, malformed responses, and timeouts.

T09 · Insecure Skill Coding Practices

Warning
Location
test-rollback-mechanism.sh:8
Finding
Predictable shared temporary directory permits symlink-based file overwrite## Vulnerability Details **File Location**: `test-rollback-mechanism.sh`, lines 8 and 81-92; cleanup at line 151 **Vulnerability Type**: Unsafe temporary-file handling **Risk Level**: Medium ### Vulnerable Code ```bash TEST_DIR="/tmp/rollback-test" ``` ```bash mkdir -p "$TEST_DIR" cp "$CONFIG_FILE" "$TEST_DIR/test-config.json" TEST_HASH=$(python3 -c " import hashlib with open('$TEST_DIR/test-config.json', 'rb') as f: print(hashlib.sha256(f.read()).hexdigest()[:8]) ") TEST_BACKUP="$TEST_DIR/test-config.json.20260301_053612.$TEST_HASH.bak" cp "$TEST_DIR/test-config.json" "$TEST_BACKUP" ``` Cleanup is also performed against the fixed path: ```bash rm -rf "$TEST_DIR" ``` ### Technical Analysis The test suite uses a constant path under globally writable `/tmp`. It does not create the directory atomically, verify its ownership, restrict permissions, or reject pre-existing symbolic links. A local attacker can pre-create `/tmp/rollback-test` and place symbolic links at expected destination paths. The `cp` commands can then follow those links and write using the privileges of the user running the test. The first copy also places the contents of `~/.openclaw/openclaw.json` into an attacker-controlled directory, potentially exposing configuration data. The deterministic backup filename includes a hash of the configuration. Although an attacker may not initially know that hash, the fixed directory remains observable and attacker-controlled, and the first predictable destination is sufficient for a symlink overwrite attempt. ### Attack Path 1. A local attacker creates `/tmp/rollback-test` before the test is run. 2. The attacker places `test-config.json` as a symbolic link to a file writable by the intended test runner. 3. The victim runs the documented test suite. 4. `mkdir -p` accepts the existing attacker-controlled directory. 5. `cp "$CONFIG_FILE" "$TEST_DIR/test-config.json"` follows the sym ...[truncated 901 chars]
Remediation
## Remediation Suggestions - Replace the fixed directory with an atomically created private directory: ```bash umask 077 TEST_DIR="$(mktemp -d "${TMPDIR:-/tmp}/rollback-test.XXXXXX")" || exit 1 trap 'rm -rf -- "$TEST_DIR"' EXIT INT TERM ``` - Do not continue if secure temporary-directory creation fails. - Ensure all temporary files remain under the newly created private directory. - Quote every path expansion, including arguments passed to `basename`. - Avoid operating on pre-existing files and reject symbolic links where practical. - Do not use a predictable hard-coded timestamp in temporary backup names. - Add a test that pre-creates the legacy fixed path and verifies that the suite neither writes to it nor follows symbolic links.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (12)

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
If the underlying behavior is only diagnostic or test-oriented while the skill claims to perform real rollback, monitoring, and protection of live configuration, users may falsely assume remediation actions are happening automatically when they are not. For a gateway configuration skill, that false assurance can directly lead to broken deployments, persistence of invalid configs, and delayed incident response.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
If the underlying behavior is only diagnostic or test-oriented while the skill claims to perform real rollback, monitoring, and protection of live configuration, users may falsely assume remediation actions are happening automatically when they are not. For a gateway configuration skill, that false assurance can directly lead to broken deployments, persistence of invalid configs, and delayed incident response.

Lp3

Medium
Category
MCP Least Privilege
Confidence
93% confidence
Finding
The skill advertises shell execution, file writes, config copying, cron setup, and service restart behavior but declares no explicit tool scope or permissions boundary. In an agent ecosystem, this increases the chance that the skill can be invoked with broader-than-expected capabilities, leading to unsafe modification of critical configuration files or command execution without clear user consent.

Missing User Warnings

Medium
Confidence
87% confidence
Finding
The skill instructs users to overwrite critical configuration files during rollback without prominently warning that this can discard legitimate recent changes or restore stale state. In the context of gateway and approval-policy files, an unsafe restore can unintentionally re-enable old settings, break access controls, or cause service disruption.

Natural-Language Policy Violations

Medium
Confidence
93% confidence
Finding
The cron example hard-codes the timezone to Asia/Shanghai, and the sample log messages are written in Chinese. The file does not indicate that this skill is region-specific or offer users a language/locale choice, which makes the locale constraint appear imposed by default.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The module advertises pre-modification protection, but in watch mode it only notices changes after they occur and then creates a backup of the already-modified file. If a bad or malicious config change is introduced, the 'backup' may preserve the corrupted state, causing rollback to fail to restore the last known-good configuration and undermining the safety guarantees of the tool.

Natural-Language Policy Violations

Medium
Confidence
98% confidence
Finding
The module docstring is entirely in Chinese, and all user-facing operational messages throughout the script are also emitted in Chinese. This imposes a locale/language choice on users without any opt-in or documented justification, which matches the language-policy violation criteria.

Description-Behavior Mismatch

Medium
Confidence
95% confidence
Finding
The top-level documentation states '监听所有 .json 修改' ('watch all .json modifications'), which implies broad JSON-file coverage. In code, watch_config_files initializes monitoring only from the CRITICAL_FILES set containing openclaw.json, exec-approvals.json, and skills.json, so behavior is materially narrower than the stated intent.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
def check_gateway_health():
    """检查 Gateway 健康状态"""
    try:
        result = subprocess.run(
            ["curl", "-s", "http://127.0.0.1:18789/api/health"],
            timeout=3,
            capture_output=True
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

Natural-Language Policy Violations

Medium
Confidence
97% confidence
Finding
User-facing comments and terminal messages throughout the script are written in Chinese, including the main status and recommendation output. There is no indication that the tool is intended only for a Chinese-speaking environment or any option for users to select another language.

Missing User Warnings

Low
Confidence
84% confidence
Finding
The script targets $HOME/.openclaw/openclaw.json, which is user-specific configuration data, and proceeds to validate, hash, and copy it. While the script logs test progress, it does not explicitly disclose that it will access and inspect this home-directory configuration file before doing so.

Missing User Warnings

Low
Confidence
86% confidence
Finding
The script creates /tmp/rollback-test and copies the user's configuration into test artifacts there, which is a file-write operation involving user data. Although progress is logged, there is no explicit disclosure in comments or startup messaging that the script will write copies of configuration content into /tmp.

Static analysis

No suspicious patterns detected.