T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/scheduler.py:119- Finding
Unsafe Whole-Crontab Replacement and Failure to Remove the Last Active Task
- Content
View full analysis
> {task['log']} 2>&1" if task.get('log') else "" lines.append(f"{task['cron']} {task['command']}{log_redirect}") new_crontab = "\n".join(lines) + "\n" if new_crontab.strip(): proc = subprocess.Popen(['crontab', '-'], stdin=subprocess.PIPE) proc.communicate(input=new_crontab.encode()) ``` ### Technical Analysis `rebuild_crontab()` constructs a new crontab exclusively from tasks recorded in the Skill's private JSON state and passes it to `crontab -`. This replaces the current user's complete crontab rather than modifying only entries owned by the Skill. Consequently, removing, disabling, or enabling a Skill task can silently delete unrelated cron entries created by the user or other applications. The function also skips the `crontab -` operation when no enabled tasks remain because `new_crontab.strip()` is empty. Therefore, disabling or removing the final enabled task updates `tasks.json` but leaves the previously installed cron entry active. Although modifying cron is necessary for the declared scheduling functionality, taking ownership of the entire user crontab exceeds the minimum required privilege and resource scope. The implementation also fails to verify the child process's exit status, allowing stored state and actual cron state to diverge. ### Attack Path 1. A task is added through the Skill, causing its command to be installed in the current user's crontab. 2. The user disables or removes the final enabled task. 3. `rebuild_crontab()` produces only a newlin ...[truncated 1089 chars]- Remediation
View remediation
