T06 · System Persistence
Error
- Location
- negotiate_safe/run_safe.py:1097
- Finding
- Automatic Installation of a Persistent System or OpenClaw Cron Job<![CDATA[ ## Vulnerability Details **File Location**: `negotiate_safe/run_safe.py:1097-1103`, `negotiate_safe/run_safe.py:2810-2974` **Vulnerability Type**: Persistent scheduled-task registration without explicit operator approval **Risk Level**: Critical ### Vulnerable Code ```python # negotiate_safe/run_safe.py:1097-1103 # Install the global cron scan job (idempotent). Both roles # need cron — investor's resume runs from the same loop as # the founder's, just dispatched on the pointer's `role`. interval = os.environ.get("CLAW_NEGOTIATE_SCAN_INTERVAL", CRON_SCAN_DEFAULT_INTERVAL) ok, err = ensure_cron(interval=interval) if not ok and err: sys.stderr.write(f"ensure_cron: {err}\n") ``` ```python # negotiate_safe/run_safe.py:2810-2860 def ensure_cron( interval: str = "30s", runner: "callable | None" = None, system_runner: "callable | None" = None, ) -> tuple[bool, str | None]: """Install the ``negotiate_safe-scan`` cron job if absent.""" prefer_system_cron = runner is None allow_system_fallback = runner is None or system_runner is not None if runner is None: runner = subprocess.run if system_runner is None: system_runner = runner def _fallback(reason: str) -> tuple[bool, str | None]: if not allow_system_fallback: return False, reason ok, fallback_err = _ensure_system_cron(runner=system_runner) if ok: return True, None return False, f"{reason}; system cron fallback failed: {fallback_err}" if prefer_system_cron: ok, err = _ensure_system_cron(runner=system_runner) if ok: return True, None # Fall through to OpenClaw cron only if the deterministic # code-level heartbeat cannot be installed on this host. ``` ```python # negotiate_safe/run_safe.py:2928-2944 add_argv = [ "openclaw", "cron", "add", "--name", CRON_JOB_NAME, "--every", interval, "--system-event", "negotiate_safe_scan", "- ...[truncated 4632 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Remove automatic scheduler installation from the negotiation mint path. 2. Require a separate, explicit operator action such as: ```bash python3 negotiate_safe/run_safe.py operator-setup --enable-background-scan ``` 3. Display the exact scheduler command, interval, execution identity, state accessed, and network destinations before requesting consent. 4. Prefer OpenClaw's scoped scheduler over modifying the operating-system crontab. 5. Do not use `--keep-after-run` unless persistence is explicitly enabled. 6. Track whether this Skill created the scheduler entry and remove only that owned entry when no active negotiations remain. 7. Add explicit commands such as `disable-background-scan` and `uninstall`. 8. On cancellation, expiration, and successful completion, check whether any active state remains and remove the scheduler when it is no longer required. 9. Quote all executable and directory paths safely if OS cron remains supported. 10. Store logs in a permission-restricted application state directory rather than a predictable shared `/tmp` path, and implement rotation. 11. Document the behavior prominently in `SKILL.md`, README setup instructions, and the authorization prompt. 12. Operate the scheduler under a dedicated, least-privileged service account with access only to this Skill's state. ]]>
