T09 · Insecure Skill Coding Practices
Warning
- Location
- janitor.js:271
- Finding
- Destructive cleanup executes by default without preview, confirmation, or explicit high-impact scope selection<![CDATA[ ## Vulnerability Details **File Location**: `janitor.js:271-326`, `janitor.js:373-376`; default invocation documented at `SKILL.md:27-28` **Vulnerability Type**: Unsafe destructive defaults and insufficient privilege scoping **Risk Level**: Medium ### Vulnerable Code ```javascript function cleanPackageManagers() { execCommand('npm cache clean --force', 'NPM Cache'); execCommand('yarn cache clean', 'Yarn Cache'); execCommand('pnpm store prune', 'PNPM Store'); execCommand('bun pm cache rm', 'Bun Cache'); removePath(path.join(NVM_DIR, '.cache'), 'NVM Version Zip Cache'); execCommand('pip cache purge', 'Python PIP Cache'); execCommand('go clean -cache -modcache', 'Go Module Cache'); removePath(path.join(HOME, '.cargo', 'registry', 'cache'), 'Rust Cargo Cache'); if (PLATFORM === 'win32') { removePath(path.join(process.env.LOCALAPPDATA || '', 'ms-playwright'), 'Playwright Browser Binaries (Win)'); removePath(path.join(process.env.LOCALAPPDATA || '', 'puppeteer'), 'Puppeteer Browser Binaries (Win)'); } else { removePath(path.join(CACHE_HOME, 'ms-playwright'), 'Playwright Browser Binaries'); removePath(path.join(CACHE_HOME, 'puppeteer'), 'Puppeteer Browser Binaries'); } removePath(path.join(os.tmpdir(), 'openclaw-tmp'), 'OpenClaw Temp Artifacts'); } function cleanDocker() { try { execSync('docker ps', { stdio: 'ignore', timeout: 5000 }); if (DEEP_CLEAN) { execCommand('docker system prune -a -f', 'Docker System Prune (All Unused Images & Containers)'); execCommand('docker builder prune -a -f', 'Docker Buildx/BuildKit Cache (Deep)'); } else { execCommand('docker system prune -f', 'Docker System Prune (Dangling Images Only)'); execCommand('docker builder prune -f', 'Docker Buildx/BuildKit Cache (Dangling)'); } } catch (e) { logAction('SKIP', 'Docker not found or daemon not run ...[truncated 4565 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Make preview mode the default and require an explicit `--apply` flag before any mutation. 2. Require explicit group selection for destructive categories, especially `--only docker` and `--only system`. 3. Never infer authorization for system cleanup solely from the process already being root. 4. Require a dedicated flag such as `--system-clean` for package autoremove and journal deletion. 5. Separate low-impact cache cleanup from resource deletion: - Keep cache cleanup in the default eligible set. - Place Docker container/network pruning, package autoremove, and journal vacuuming behind distinct options. 6. Remove forced confirmation flags such as `-y` and `-f` unless the user has explicitly approved the exact operation. 7. Correct the Docker description because `docker system prune -f` is not limited to dangling images. 8. Update `SKILL.md` so generic requests trigger a dry run first, followed by a summary and explicit user confirmation. 9. Add tests proving that: - A flagless invocation never mutates state. - Root execution does not implicitly enable system cleanup. - Docker and system operations require explicit authorization. ]]>
