T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/config_guard.py:88
- Finding
- Predictable Backup Path Permits Symlink-Based File Overwrite## Vulnerability Details **File Location**: `scripts/config_guard.py`, lines 88–89 **Vulnerability Type**: Predictable and non-exclusive backup-file creation **Risk Level**: Medium ```python timestamp = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%SZ") backup_path = path.with_name(f"{path.name}.bak.{timestamp}") shutil.copy2(path, backup_path) ``` ### Technical Analysis The backup filename is based on a UTC timestamp with one-second precision, making its value predictable. The destination is not reserved atomically using exclusive-creation semantics before `shutil.copy2()` writes to it. If a destination path already exists as a symbolic link, `shutil.copy2()` follows that link and writes to its target. Consequently, an attacker with write access to the configuration directory can pre-create a symlink at the predicted backup path and redirect the backup write to another file. This is a time-of-check/time-of-use and unsafe-file-creation weakness. It undermines the script’s stated backup and rollback guarantees. ### Attack Path 1. The attacker has write access to the directory containing the OpenClaw configuration file. 2. The attacker predicts the backup filename from the configuration filename and current UTC timestamp, for example, `openclaw.json.bak.20260911-120000Z`. 3. Before the backup command reaches `shutil.copy2()`, the attacker creates that path as a symbolic link to a target file. 4. The user invokes the script’s `backup` command during the predicted second. 5. `shutil.copy2()` follows the attacker-controlled symbolic link and overwrites the linked target with the configuration contents. ### Impact Assessment The attacker can overwrite or corrupt files that are writable by the account running the Skill. The operation does not independently grant additional operating-system privileges, so its scope is limited to the invoking user’s existing write permissions. Potential effects include denial of service, corruption of user-owned application ...[truncated 206 chars]
- Remediation
- ## Remediation Suggestions Create and reserve the backup destination atomically rather than constructing a predictable pathname and passing it directly to `shutil.copy2()`. - Use `tempfile.mkstemp()` in the configuration directory, or use `os.open()` with `O_CREAT | O_EXCL` and, where supported, `O_NOFOLLOW`. - Copy the configuration through the securely opened file descriptor so the destination cannot be replaced between creation and writing. - Generate a cryptographically unpredictable suffix instead of relying only on a second-resolution timestamp. - Explicitly reject symbolic-link destinations. - Apply restrictive permissions to the backup, such as matching the source file’s intended private access without briefly exposing broader permissions. - Flush and close the backup before reporting success. - If a human-readable timestamp is required, include it as part of the name while retaining a random suffix and exclusive creation. - Add tests that pre-create a destination symlink and verify that the backup operation fails safely without modifying the symlink target.
