Back to skill

Security audit

EasyClaw Config Migration

Security checks for vulnerabilities and agentic risk

Overview

This migration skill is mostly aligned with its purpose, but it can expose gateway tokens in output and create extra plaintext config backups, so it should be reviewed before use.

Use this only if you are comfortable with it reading EasyClaw/OpenClaw configuration files and modifying OpenClaw settings. Before running `--apply`, patch or review the merge script so token values are redacted in all output and backups are created with owner-only permissions; avoid sharing dry-run logs and rotate any gateway token that may already have appeared in output.

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

Error
Location
scripts/merge_easyclaw_config.py:76
Finding
Authentication Tokens Are Disclosed in Migration Output<![CDATA[ ## Vulnerability Details **File Location**: `scripts/merge_easyclaw_config.py`, lines 13–20 and 75–78 **Vulnerability Type**: Sensitive information exposure through standard output **Risk Level**: High ### Vulnerable Code ```python MAPPINGS = [ ('commands.native', 'commands.native'), ('commands.nativeSkills', 'commands.nativeSkills'), ('commands.restart', 'commands.restart'), ('gateway.mode', 'gateway.mode'), ('gateway.auth.mode', 'gateway.auth.mode'), ('gateway.auth.token', 'gateway.auth.token'), ] ``` ```python print('Planned changes:') for path, old, new in changes: print(f'- {path}: {old!r} -> {new!r}') ``` ### Technical Analysis The migration list explicitly includes `gateway.auth.token`. When that value differs between the source and target configurations, the script adds the original and replacement values to `changes`. Lines 76–78 then print both values using their raw `repr` representations. No path-sensitive redaction is applied before the values are written to standard output. This behavior affects both dry-run and `--apply` execution. It also conflicts with the sensitive-data handling requirement in `SKILL.md`, which directs the Skill to redact tokens, secrets, and authentication blobs. Although the reporting script contains a redaction function, that protection is not reused by the migration script. ### Attack Path 1. An EasyClaw bridge configuration contains a `gateway.auth.token`. 2. The active OpenClaw configuration either contains a different token or does not contain the field. 3. A user or Agent runs the documented command: ```bash python3 scripts/merge_easyclaw_config.py ``` or: ```bash python3 scripts/merge_easyclaw_config.py --apply ``` 4. The script prints the existing and replacement token values in plaintext. 5. An attacker with access to the terminal transcript, Agent conversation, CI output, centralized logs, or captured process output retrieves the token. 6. If the t ...[truncated 679 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Never print raw values for paths containing sensitive terms such as `token`, `secret`, `password`, `credential`, or authentication keys. 2. For sensitive changes, print only the field name and a neutral status: ```python print(f'- {path}: <redacted> -> <redacted>') ``` 3. Introduce a shared redaction function and apply it to every diagnostic, dry-run, error, and success output path. 4. Prefer an explicit sensitive-path allowlist because field-name substring matching can miss unusually named credentials. 5. Add automated tests verifying that known token values never appear in captured standard output or standard error during dry-run and apply operations. 6. Rotate any gateway tokens that may already have been exposed through prior migration logs. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/merge_easyclaw_config.py:86
Finding
Secret-Bearing Configuration Backups May Be Created with Permissive Permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/merge_easyclaw_config.py`, lines 86–89 **Vulnerability Type**: Insecure storage permissions for plaintext credentials **Risk Level**: Medium ### Vulnerable Code ```python ts = datetime.now().strftime('%Y%m%d-%H%M%S') backup = OPENCLAW_CFG.with_name(f'{OPENCLAW_CFG.name}.bak.easyclaw-{ts}') backup.write_text(json.dumps(target, indent=2, ensure_ascii=False) + '\n') OPENCLAW_CFG.write_text(json.dumps(updated, indent=2, ensure_ascii=False) + '\n') ``` ### Technical Analysis The script writes the entire existing OpenClaw configuration into a timestamped backup. That configuration can contain `gateway.auth.token` and other sensitive data. `Path.write_text()` creates a new file using permissions derived from the process umask. The script does not explicitly require owner-only permissions, inspect the resulting mode, or preserve the restrictive permissions of the original configuration. Under a permissive umask, the newly created backup can become readable by other local users. The backup is stored as an additional plaintext credential copy and no retention or secure-removal policy is implemented. The target rewrite also uses `write_text()` directly rather than an atomic, permission-preserving replacement, although the confirmed confidentiality concern is clearest for the newly created backup. ### Attack Path 1. The active `~/.openclaw/openclaw.json` contains authentication tokens or other credentials. 2. The migration is run with `--apply` in an environment with a permissive umask. 3. The script creates a new timestamped backup using default creation permissions. 4. The resulting backup is group-readable or world-readable. 5. Another local account, process, or service with filesystem access to the directory reads the backup. 6. The attacker extracts the stored credentials and uses them against services that accept those credentials. This path requires local filesystem access and directory traversa ...[truncated 633 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create backup files explicitly with owner-only mode `0600`, using exclusive creation to avoid collisions: ```python fd = os.open(backup, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600) with os.fdopen(fd, 'w', encoding='utf-8') as handle: handle.write(json.dumps(target, indent=2, ensure_ascii=False) + '\n') ``` 2. Verify that `~/.openclaw` is owned by the current user and has restrictive directory permissions before writing sensitive files. 3. Preserve or strengthen the original configuration's ownership and permission mode when replacing it. 4. Write the updated configuration to a securely created temporary file in the same directory, flush and synchronize it, set mode `0600`, and atomically replace the target. 5. Document a backup-retention policy and provide a safe mechanism for removing obsolete backups. 6. Add permission tests that run under permissive umasks and verify that backups and rewritten configurations remain owner-readable and owner-writable only. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (6)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The merge behavior largely matches: it compares a source config to ~/.openclaw/openclaw.json, performs a selective merge of predefined settings, supports dry-run versus apply, and creates a backup before writing. However, the description claims it locates EasyClaw desktop/runtime config files and can be used when a user asks where EasyClaw stores its config. The code does neither: it only expects a preexisting hardcoded bridge file ~/.openclaw/easyclaw.json and exits if that file is missing. That is a material mismatch in resource access and capability, even though the core merge/apply logic is aligned.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The code is a reporting script, not a migration tool. It loads JSON from the EasyClaw desktop config, a bridge config at ~/.openclaw/easyclaw.json, and the OpenClaw config, then prints existence status, redacted contents, and selected field comparisons. This aligns partially with the 'where is config stored' and 'migration report' portions of the description, but the core declared purpose emphasizes safely generating or applying a selective merge into OpenClaw. No file writes, merge computation artifact, backup handling, or config application occur. Therefore the description materially overstates the skill's capabilities and primary purpose.

Lp3

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding
The skill instructs reading and modifying user configuration files, including applying merges and creating backups, but it does not declare any explicit tool scope such as allowed-tools or permissions. That creates an authorization gap where a host system or reviewer cannot clearly constrain file read/write behavior, increasing the chance of unintended file access or modification.

Session Persistence

Medium
Category
Rogue Agent
Content
```

Behavior:
- create a timestamped backup of `~/.openclaw/openclaw.json`
- merge only supported fields from `~/.openclaw/easyclaw.json`
- print changed paths
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.

Session Persistence

Medium
Category
Rogue Agent
Content
def main() -> int:
    parser = argparse.ArgumentParser(description='Merge supported EasyClaw settings into OpenClaw config.')
    parser.add_argument('--apply', action='store_true', help='Write changes to ~/.openclaw/openclaw.json')
    args = parser.parse_args()

    if not BRIDGE_CFG.exists():
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.

Natural-Language Policy Violations

Low
Confidence
80% confidence
Finding
The document references `app.language` as a desktop-only field to be reported, which encodes a user language/locale preference. Because the guidance treats this setting as part of migration/reporting behavior without any indication of user choice or opt-in, it may conflict with language/locale policy expectations that user language preferences should not be imposed or handled without explicit user control.

Static analysis

No suspicious patterns detected.