Automatically backs up files before deletion to timestamped folders, allows restoring deleted files, lists backups, and cleans expired backups and logs.
---
name: delete-recovery
description: File deletion recovery skill v0.11.0. Back up files before deletion (to `delete_backup/YYYYMMDDHHMM/`), restore from backup, search via manifest. SHA256 integrity + path-traversal checks + workspace-root confinement. Auto-cleanup 7d/30d. **v0.11.0: new security audit fixes - path traversal detection, dir backup fallback, SHA256 integrity clarification.** **v0.9.0: dest_path validation, dry-run token gate, trigger disambiguation.** **v0.8.1: workspace_cleaner disabled-by-default; backup failures block deletion.** **v0.8.0: Added workspace_cleaner.** **v0.7.0: allowed_roots defaults to workspace root; manifest paths HMAC-encrypted.**
**⚠️ Security trade-offs (know them before deploying):**
- Backups are stored in `{workspace}/.delete_recovery/delete_backup/`, **outside** the skill directory - they survive skill deletion but are not protected by skill folder permissions.
- `allowed_roots` defaults to workspace root (v0.7.0, fixed v0.11.0) - restores confined to `{workspace}` tree; pass `allowed_roots=[]` explicitly to remove confinement (legacy restores only).
- Manifest paths are HMAC-SHA256 encrypted (v0.7.0) - original paths no longer readable in manifest.jsonl; filename/description still in plaintext. SHA256 records are integrity checks only (detect accidental modification); they are NOT cryptographically signed and do not protect against a local attacker who can modify both backup files and their metadata.
- workspace_cleaner is **disabled by default** (v0.8.1) - must opt-in explicitly; first run requires dry-run + token confirm-first-run.
- workspace_cleaner backup failures **block deletion** (v0.8.1) - files are NOT deleted if backup fails.
- No install-time integrity verification - deploy only in trusted environments.
- Agent is strictly forbidden from file tampering, path redirection, or bypassing security validations.
**Use cases (triggers):**
1. User wants to delete a file and needs a backup first
2. User accidentally deleted a file and wants to recover it
3. User wants to see available backups
4. User wants to manually clean up a specific backup
5. User wants to verify backup integrity without restoring
6. User wants to search for a deleted file by name or keyword
7. User wants to schedule automatic workspace cleanup (v0.8.1+: **opt-in only, token-gated**)
**Triggers / keywords (v0.11.0: specific, unambiguous phrases only - broad housekeeping phrases removed):**
- `delete file` / `删除文件` - backup before deletion
- `recover deleted file` / `误删恢复` / `恢复文件` / `undelete` - restore from backup
- `list backups` / `查看备份` - list available backups
- `clean up backup` / `清理备份` - manually clean a specific backup
- `verify backup` / `验证备份完整性` / `check backup integrity` - integrity check without restoring
- `search deleted file` / `搜索已删除文件` / `检索删除记录` - search manifest
- `workspace_cleaner` - explicitly invoke workspace cleaner (not "clean workspace" or "定时清理" alone)
**⚠️ Agent Behavior Constraints (MANDATORY):**
- Agent is ONLY permitted to: backup files, restore files, list backups, **search deleted files via manifest**, clean backups, undelete, verify backup integrity, manual cleanup, **manage workspace_cleaner whitelist/config, trigger workspace cleanup**
- Agent is ABSOLUTELY FORBIDDEN from: file content tampering, path redirection, path traversal attacks, backup substitution, bypassing SHA256 integrity verification, bypassing PATH cross-validation, unauthorized deletion, log tampering
- **Exception:** Using `--force` to bypass the SHA256 *existence* check is permitted **only** for pre-v0.3.0 legacy backups that lack SHA256 records. SHA256 correctness check, PATH cross-validation, traversal detection, and dest_path validation are **never** bypassable under any circumstances.
- All restore operations MUST pass SHA256 + PATH cross-validation + traversal detection + dest_path validation
---
### 中文
---
## 概述
文件误删恢复技能 v0.11.0。删除文件前先将文件备份到带时间戳的文件夹(`delete_backup/YYYYMMDDHHMM/`),备份时计算 SHA256 哈希并存储,恢复时验证完整性并检查路径安全(检测 `../` 等路径遍历序列)。恢复后自动删除备份(保留原始文件结构)。
**v0.11.0 安全修复(针对 security audit 5项发现):**
- Finding 1:`--force` 语义统一文档化 - `--force` 仅跳过 SHA256 **存在性**检查;SHA256 正确性检查、PATH 跨验、遍历检测、dest_path 验证**始终强制执行**,不可绕过
- Finding 2:`allowed_roots` 默认值修正 - 从 `[]`(无限制)改为 `[WORKSPACE_ROOT]`(限制为 workspace 树),与文档描述一致;传入 `allowed_roots=[]` 可恢复无限制行为(仅用于遗留恢复)
- Finding 3:`full_restore_check()` 修复 - `dest_path` 参数不再被静默忽略,现通过 `verify_integrity_and_path()` 完整验证(遍历 + 与 original_path 一致性 + allowed_roots)
- Finding 4:`confirm-first-run` token 机制 - 每次 `dry-run` 生成唯一 token,确认时必须提供有效未使用的 token,防止未预览就启用的绕过
- Finding 5:触发词收窄 - 移除 "clean workspace"、"定时清理" 等宽泛触发词,仅保留 `workspace_cleaner` 等明确触发词
**v0.8.1 安全修复(针对 ASI02 风险分析):**
- workspace_cleaner **默认禁用**(enabled=False),需显式 opt-in
- 首次运行必须先 `dry-run` 预览并 `confirm-first-run <token>` 确认
- **备份失败阻断删除**:任何备份失败(delete_recovery + manual fallback 均失败)时,对应文件不会被删除
**v0.8.0 workspace_cleaner:**
- 定时(默认24小时)扫描 workspace 下的临时文件和过期文件(默认7天),自动备份后清理
- 支持白名单配置(文件扩展名/文件名/文件夹名),白名单内不清理
- 核心文件(AGENTS.md、SOUL.md 等)和技能目录始终保护
- 支持手动触发 `dry-run` 预览
- 数据文件独立存放于 `{workspace}/.delete_recovery/workspace_cleaner/`,技能删除后配置仍保留
**v0.7.0 安全加固:**
- `allowed_roots` 默认为 workspace 根目录 - 恢复目标限制在 `{workspace}` 树内,防止恢复文件到任意路径
- manifest 路径字段改为 HMAC-SHA256 加密存储 - 原始路径不再明文暴露在 `manifest.jsonl` 中
⚠️ **版本说明:** v0.1.0~v0.6.0 已淘汰(`DEPRECATED`),功能说明保留仅供参考。请始终使用 **v0.7.0** 或更高版本。
## 触发场景
1. 用户要删除文件,希望先备份
2. 用户误删了文件,想要恢复
3. 用户想查看有哪些可用的备份
4. 用户想手动清理某个备份
5. 用户想验证备份是否被篡改(不执行恢复)
6. 用户想通过文件名/功能/路径关键字检索已删除的文件
7. 用户想自动清理 workspace 下的临时文件和过期文件
**触发词:** 删除文件、误删恢复、恢复文件、查看备份、清理备份、验证备份完整性、搜索已删除文件、检索删除记录、workspace_cleaner
### English
## Overview
File deletion recovery skill v0.11.0. Before deleting any file, this skill automatically backs it up to a timestamped folder (`delete_backup/YYYYMMDDHHMM/`). Backups include SHA256 integrity hashes to detect post-backup tampering. Restore paths are validated to block path-traversal sequences. Backups auto-removed 7 days; logs auto-cleaned 30 days.
**v0.11.0 security audit fixes:**
- Finding 1: `--force` docs unified - `--force` bypasses SHA256 *existence* check only (for pre-v0.3.0 legacy backups). SHA256 correctness, PATH cross-validation, traversal detection, and dest_path validation are **never** bypassable.
- Finding 2: `allowed_roots` default corrected - now defaults to `[WORKSPACE_ROOT]` (was `[]` meaning no restriction). Callers relying on documented defaults were unknowingly allowing restores to arbitrary paths. Pass `allowed_roots=[]` to restore no-confinement for legacy restores.
- Finding 3: `full_restore_check()` fixed - `dest_path` parameter now passes through to `verify_integrity_and_path()` and is fully validated (traversal + equality with original_path + allowed_roots), closing the gap where the documented single entry point silently ignored the actual restore destination.
- Finding 4: `confirm-first-run` token mechanism - each dry-run generates a cryptographically random token; confirm-first-run requires a valid un-used token, preventing the bypass where cleanup could be enabled without ever reviewing the dry-run preview.
- Finding 5: trigger disambiguation - broad housekeeping phrases like "clean workspace" or "定时清理" removed; only specific, unambiguous triggers like `workspace_cleaner` activate deletion-oriented behaviour.
**v0.8.1 workspace_cleaner security fix (addressing ASI02):** workspace_cleaner is **disabled by default** - explicit opt-in required; first run requires dry-run + token-based confirm-first-run; backup failure blocks deletion entirely.
**v0.8.0 workspace_cleaner:** Scheduled (default 24-hour) scan of workspace for temp files and expired files (default 7 days), auto-backup then delete; whitelist support; core files always protected.
⚠️ **Version note:** v0.1.0~v0.6.0 are deprecated (`DEPRECATED`). Always use **v0.7.0** or higher.
## Trigger Scenarios
1. User wants to delete a file and needs a backup first
2. User accidentally deleted a file and wants to recover it
3. User wants to see available backups
4. User wants to manually clean up a specific backup
5. User wants to verify backup integrity without restoring
6. User wants to search for a deleted file by name or keyword
7. User wants to schedule automatic workspace cleanup
**Triggers:** delete file, recover deleted file, list backups, clean up backup, undelete, verify backup, check backup integrity, search deleted file, find deleted file, workspace_cleaner
## 核心命令 / Core Commands
### 中文
### delete_recovery.py - 备份恢复核心
```
{workspace}/skills/delete-recovery/scripts/delete_recovery.py
```
| 命令 | 说明 | 备注 |
|------|------|------|
| `backup <file_path> [original_path] [description]` | 备份文件到带时间戳文件夹 | v0.7.0 |
| `search <keyword>` | 按文件名/简介/路径关键字检索已删除文件 | v0.7.0 |
| `restore <folder> <safe_name> [--keep-backup] [--force]` | 从备份恢复文件 | v0.7.0 |
| `verify <folder> <safe_name>` | 验证备份完整性(SHA256 + PATH) | v0.7.0 |
| `list` | 查看备份列表 | v0.7.0 |
| `delete_backup <folder>` | 删除指定备份 | v0.7.0 |
| `cleanup` | 手动触发过期备份+日志清理 | v0.7.0 |
| `log [lines]` | 查看操作日志 | v0.7.0 |
**`--force` 说明(v0.11.0 明确):**
- `--force` **仅**在备份文件无 SHA256 记录时(pre-v0.3.0 遗留备份)用于跳过 SHA256 **存在性**检查
- SHA256 **正确性**检查(哈希匹配)、PATH 跨验、遍历检测、dest_path 验证**始终强制执行**,不可用 `--force` 绕过
- 适用场景:恢复 v0.3.0 之前创建的备份(当时未记录 SHA256)
### workspace_cleaner.py - workspace 定时清理(v0.11.0 强制安全修复)
```
{workspace}/skills/delete-recovery/scripts/workspace_cleaner.py
```
**v0.11.0 安全流程(首次启用必须按顺序执行):**
```
1. python workspace_cleaner.py status # 查看当前状态
2. python workspace_cleaner.py enable # 启用 workspace_cleaner(opt-in,默认 False)
3. python workspace_cleaner.py dry-run # 预览清理范围 + 生成一次性 token
4. python workspace_cleaner.py confirm-first-run <token> # 凭 token 确认,解锁实际清理
5. python workspace_cleaner.py run # 执行实际清理(满足时间间隔时)
```
| 命令 | 说明 |
|------|------|
| `python workspace_cleaner.py run` | 手动触发一次清理(enabled=True + first_run_confirmed=True + 满足时间间隔) |
| `python workspace_cleaner.py dry-run` | 预览哪些文件将被清理(不实际删除,始终可用;生成一次性 token) |
| `python workspace_cleaner.py status` | 查看定时器状态和配置(含 enabled / first_run_confirmed / token 状态) |
| `python workspace_cleaner.py enable` | 启用 workspace_cleaner(opt-in,默认 False) |
| `python workspace_cleaner.py disable` | 禁用 workspace_cleaner(opt-out) |
| `python workspace_cleaner.py confirm-first-run <token>` | 凭 dry-run 生成的 token 确认首次运行,解锁实际清理 |
| `python workspace_cleaner.py show-whitelist` | 查看当前白名单 |
| `python workspace_cleaner.py add-whitelist <path> [--type file\|folder\|ext]` | 添加白名单项 |
| `python workspace_cleaner.py remove-whitelist <path>` | 移除白名单项 |
| `python workspace_cleaner.py set-interval <hours>` | 设置清理间隔(小时) |
| `python workspace_cleaner.py set-expire-days <days>` | 设置文件过期天数 |
**v0.11.0 `confirm-first-run` token 机制说明:**
- 每次执行 `dry-run` 生成一个加密随机 token(32字节 hex),有效期 24 小时
- `confirm-first-run <token>` 需要提供有效且未使用的 token
- token 被使用后即失效,需重新 `dry-run` 获取新 token
- 这样确保用户必须先看到 dry-run 预览结果才能启用清理
### English
### delete_recovery.py - Backup & Recovery Core
```
{workspace}/skills/delete-recovery/scripts/delete_recovery.py
```
| Command | Description | Notes |
|---------|-------------|-------|
| `backup <file_path> [original_path] [description]` | Backup file to timestamped folder | v0.7.0 |
| `search <keyword>` | Search deleted files by name/description/path | v0.7.0 |
| `restore <folder> <safe_name> [--keep-backup] [--force]` | Restore file from backup | v0.7.0 |
| `verify <folder> <safe_name>` | Verify backup integrity (SHA256 + PATH) | v0.7.0 |
| `list` | List all backups | v0.7.0 |
| `delete_backup <folder>` | Delete specified backup | v0.7.0 |
| `cleanup` | Manual trigger expired backup + log cleanup | v0.7.0 |
| `log [lines]` | View operation logs | v0.7.0 |
**`--force` behaviour (v0.11.0 clarified):**
- `--force` bypasses the SHA256 *existence* check **only** (for pre-v0.3.0 legacy backups that lack SHA256 records).
- SHA256 correctness check, PATH cross-validation, traversal detection, and dest_path validation are **always enforced**, even with `--force`. Never use `--force` unless you understand the backup predates v0.3.0.
### workspace_cleaner.py - Workspace Scheduled Cleanup (v0.11.0)
| Command | Description |
|---------|-------------|
| `python workspace_cleaner.py run` | Trigger cleanup (respects interval)
| `python workspace_cleaner.py dry-run` | Preview files to clean (no actual deletion; generates one-time token)
| `python workspace_cleaner.py status` | View timer status and config
| `python workspace_cleaner.py confirm-first-run <token>` | Confirm dry-run results with token (v0.11.0: token required)
| `python workspace_cleaner.py show-whitelist` | View current whitelist
| `python workspace_cleaner.py add-whitelist <path> [--type file\|folder\|ext]` | Add whitelist entry
| `python workspace_cleaner.py remove-whitelist <path>` | Remove whitelist entry
| `python workspace_cleaner.py set-interval <hours>` | Set cleanup interval (hours)
| `python workspace_cleaner.py set-expire-days <days>` | Set file expiration days
### 中文
## 安装
### 前提条件
- Python 3.8+
- 已安装 ClawHub CLI:`npm i -g clawhub`
- 已登录 ClawHub:`clawhub login`
### 安装步骤
```bash
# 通过 ClawHub 安装技能
clawhub install delete-recovery
# 查看已安装的技能
clawhub list
```
### English
## Installation
### Prerequisites
- Python 3.8+
- ClawHub CLI installed: `npm i -g clawhub`
- ClawHub logged in: `clawhub login`
### Installation Steps
```bash
# Install skill via ClawHub
clawhub install delete-recovery
# List installed skills
clawhub list
```
---
## delete_recovery.py 命令详解
### 中文
所有命令通过执行脚本实现,路径:
```
{workspace}/skills/delete-recovery/scripts/delete_recovery.py
```
### 1. 备份文件(删除前必做)
```bash
python delete_recovery.py backup <file_path> [original_path] [description]
```
- `file_path`:要备份的文件完整路径
- `original_path`(可选):原始文件路径,恢复时用于定位,默认为 `file_path`
- `description`(可选):功能简介,建议 ≤6 字,如"飞书配置""工作报告",默认为文件名
备份时自动计算并存储 SHA256 哈希 + 原始路径到 `.sha256` 文件,防止备份文件被替换。备份后自动将(文件名、功能简介、路径)写入 `manifest.jsonl`,支持 `search` 检索。
**返回示例:**
```json
{"ok": true, "folder": "202603261130", "file": "C__Users__user__Desktop__test.txt", "description": "工作报告"}
```
### 2. 搜索已删除文件
```bash
python delete_recovery.py search <keyword>
```
在 manifest.jsonl 中按文件名、功能简介或路径关键字模糊搜索,返回匹配的备份位置和恢复命令。
- `keyword`:检索关键词(大小写不敏感, substring 匹配)
**返回示例:**
```json
{
"keyword": "报告",
"results": [
{
"ts": "202603281030",
"folder": "202603281030",
"safe_name": "C__Users__user__Desktop__report.docx",
"filename": "report.docx",
"description": "工作报告",
"path": "C:/Users/user/Desktop/report.docx"
}
],
"count": 1
}
```
### 3. 恢复文件
```bash
python delete_recovery.py restore <backup_folder> <safe_name> [--keep-backup] [--force]
```
- `backup_folder`:备份文件夹名(如 `202603261130`)
- `safe_name`:备份文件名(脚本自动将路径中的 `/`、`\`、`:` 替换为 `__`)
- `--keep-backup`:可选,恢复成功后**保留**该备份文件夹(默认自动删除)
- `--force`:强制恢复无 SHA256 记录的旧备份(**仅**跳过 SHA256 存在性检查;SHA256 正确性、PATH 跨验、遍历检测、dest_path 验证始终强制执行)
恢复前验证 SHA256 完整性 + PATH 交叉验证 + 路径遍历检测 + dest_path 验证(v0.11.0),任一验证失败均拒绝恢复。
**返回示例:**
```json
{"ok": true, "restored_to": "C:\\Users\\user\\Desktop\\test.txt", "backup_deleted": true}
```
### 4. 验证备份完整性
```bash
python delete_recovery.py verify <backup_folder> <safe_name>
```
在不恢复的情况下验证备份完整性(SHA256 哈希匹配 + PATH 交叉验证)。
### 5. 查看备份列表
```bash
python delete_recovery.py list
```
返回所有备份文件夹列表,最新在前。
### 6. 手动清理备份
```bash
python delete_recovery.py delete_backup <folder>
```
删除指定的备份文件夹(同时清理 manifest 索引)。
### 7. 手动触发清理
```bash
python delete_recovery.py cleanup
```
立即执行过期备份(7天)和日志(30天)全量清理,忽略时间触发限制。
### 8. 查看日志
```bash
python delete_recovery.py log [lines]
```
查看最近 N 行操作日志(默认50行)。
---
## workspace_cleaner.py 命令详解
### 中文
**v0.11.0 首次启用流程(必须按顺序):**
```bash
# Step 1: 查看状态
python workspace_cleaner.py status
# Step 2: 启用功能
python workspace_cleaner.py enable
# Step 3: 预览清理范围 + 获取 token
python workspace_cleaner.py dry-run
# → 返回 dry_run_token,记下这个 token
# Step 4: 凭 token 确认
python workspace_cleaner.py confirm-first-run <上一步返回的token>
# Step 5: 执行实际清理
python workspace_cleaner.py run
```
**定时清理设置(推荐通过 cron 定期触发 `run`):**
| 命令 | 说明 |
|------|------|
| `set-interval <hours>` | 设置清理间隔(小时),最小 1 小时 |
| `set-expire-days <days>` | 设置文件过期天数(0 = 立即删除 temp 文件) |
### English
### 1. Check status
```bash
python workspace_cleaner.py status
```
Shows: enabled flag, first-run confirmed flag, current token status, interval, expiry days.
### 2. Enable + First-run flow (v0.11.0)
```bash
# Enable
python workspace_cleaner.py enable
# Preview + get token
python workspace_cleaner.py dry-run
# → returns "dry_run_token": "<hex>" - note it
# Confirm with token
python workspace_cleaner.py confirm-first-run <token>
# Run
python workspace_cleaner.py run
```
### 3. Whitelist management
```bash
python workspace_cleaner.py show-whitelist
python workspace_cleaner.py add-whitelist <path> [--type file|folder|ext]
python workspace_cleaner.py remove-whitelist <path>
```
### 4. Configure schedule
```bash
python workspace_cleaner.py set-interval 24 # every 24 hours
python workspace_cleaner.py set-expire-days 7 # files older than 7 days
```
---
## 注意事项 / Notes
### 中文
1. **删除前必备份**:所有删除操作前都应先调用 `backup`,防止误删
2. **恢复时目标冲突**:如果原位置已有文件,会自动将旧文件暂存到 `temp_existing/` 目录
3. **恢复后自动删备份**:默认情况下,恢复成功后会自动删除对应备份(多文件时等全部恢复完再清理);使用 `--keep-backup` 可保留
4. **路径编码**:备份文件名将 `\`、`/`、`:` 替换为 `__`,恢复时需使用转换后的名称
5. **时间触发清理**:7天备份清理和30天日志清理改为时间触发(默认24小时间隔),不再每次命令都执行全量扫描;`cleanup` 命令本身不受影响,仍立即执行全量清理
6. **manifest 增量操作**:restore/delete_backup 时按需压缩 manifest(候选集≤100条时全量rewrite,>100条时追加墓碑标记);list/search/log 时自动检查并触发增量压缩
7. **安全验证**:restore 时自动进行 SHA256 完整性 + PATH 交叉验证 + 遍历检测 + dest_path 验证(v0.11.0),如验证失败会明确报错
8. **旧备份恢复**:无 SHA256 记录的旧备份使用 `restore --force` 可强制恢复(仅跳过 SHA256 存在性检查;完整性、PATH、dest_path 验证不可绕过)
9. **检索索引**:`backup` 自动追加索引,`restore` 成功后自动剔除;过期备份文件夹对应的索引随 `cleanup` 或脚本启动时自动清理
10. **workspace 目录限制**(v0.7.0+v0.11.0):恢复目标被限制在 workspace 根目录内,阻止恢复文件到任意系统路径;如需恢复 workspace 外的文件,需显式传入 `allowed_roots=[]`
11. **manifest 路径加密**(v0.7.0):manifest 中的原始路径字段已改为 HMAC-SHA256 加密,无法通过直接查看 manifest 获取原始路径;解密完全由 `.path` 文件负责
12. **workspace_cleaner 默认禁用**(v0.8.1):enabled 默认为 False,需 `enable` 命令显式启用;首次运行需先 dry-run + token confirm-first-run
13. **workspace_cleaner 备份失败阻断删除**(v0.8.1):delete_recovery.py 备份失败且 manual fallback 也失败时,对应文件不会被删除,记录到 `skipped_backup_failed`
14. **workspace_cleaner 定时清理**(v0.8.0):需通过 cron 或定期触发;默认24小时间隔,7天过期文件;核心文件和技能目录始终保护
15. **workspace_cleaner 备份降级**(v0.8.0):delete_recovery.py 备份失败时自动降级为手动备份;手动备份也失败则跳过该文件(不删除)
16. **confirm-first-run token 机制**(v0.11.0):dry-run 生成一次性 token(24小时有效),confirm-first-run 必须提供有效 token 才能解锁首次清理
17. **触发词收窄**(v0.11.0):"clean workspace"、"定时清理" 等宽泛短语不再激活 workspace_cleaner;仅 `workspace_cleaner` 等明确触发词有效
### English
1. **Always backup before deleting**: Call `backup` before any deletion
2. **Restore target conflict**: Existing files moved to `temp_existing/` before restoring
3. **Auto-delete backup after restore**: Default behaviour (multi-file: all restored → then delete); use `--keep-backup` to retain
4. **Path encoding**: `\`, `/`, `:` replaced with `__` in backup filenames
5. **Time-triggered cleanup**: 7-day backup and 30-day log cleanup are time-triggered (default 24-hour interval), not run on every command; `cleanup` command itself still runs full cleanup immediately
6. **Incremental manifest**: restore/delete_backup use on-demand manifest compaction; list/search/log auto-check and compact oversized manifests
7. **Security checks**: Restore automatically fails with clear error if SHA256 integrity, PATH cross-validation, traversal, or dest_path validation (v0.11.0) fails
8. **Legacy backup restore**: Backups without SHA256 records use `restore --force` to force restore (only bypasses SHA256 existence check; integrity, PATH, dest_path validation non-bypassable)
9. **Manifest index**: `backup` auto-indexes; `restore` auto-removes index entry; stale entries pruned on `cleanup` or script startup
10. **Workspace root confinement** (v0.7.0+v0.11.0): Restore destinations are confined to workspace root - files cannot be restored to arbitrary system paths; pass `allowed_roots=[]` to restore outside workspace (legacy restores only)
11. **Manifest path encryption** (v0.7.0): Original paths in manifest.jsonl are HMAC-SHA256 encrypted - cannot be read by inspecting the manifest file; decryption always uses the `.path` file in the backup folder
12. **workspace_cleaner opt-in** (v0.8.1): `enabled` defaults to False; must explicitly `enable`; first run requires dry-run + token confirm-first-run
13. **workspace_cleaner backup failure blocks deletion** (v0.8.1): If both delete_recovery and manual fallback fail for a file, that file is NOT deleted - reported in `skipped_backup_failed`
14. **workspace_cleaner scheduled cleanup** (v0.8.0): Requires cron or periodic triggering; default 24-hour interval, 7-day expiry; core files and skill directory always protected
15. **workspace_cleaner backup fallback** (v0.8.0): Falls back to manual copy if delete_recovery.py backup fails; skips (does not delete) if even manual backup fails
16. **confirm-first-run token mechanism** (v0.11.0): dry-run generates a one-time token (24h validity); confirm-first-run requires a valid un-used token to unlock first cleanup
17. **Trigger disambiguation** (v0.11.0): broad housekeeping phrases like "clean workspace" or "定时清理" no longer activate workspace_cleaner; only specific triggers like `workspace_cleaner` are active
---
## Security Audit Findings Addressed (v0.11.0)
| Finding | Description | Fix |
|---------|-------------|-----|
| Finding 1 (93%) | `--force` docs inconsistent - ambiguous whether integrity checks still run | SKILL.md and docstrings unified: `--force` bypasses SHA256 *existence* only; all other checks (SHA256 correctness, PATH cross-validation, traversal, dest_path) are **always enforced** |
| Finding 2 (96%) | `allowed_roots` defaults to `[]` (no restriction) despite docs saying restore confined to workspace root | `safe_path.py` now defaults to `[WORKSPACE_ROOT]`; pass `allowed_roots=[]` explicitly for no-confinement legacy restores |
| Finding 3 (93%) | `full_restore_check()` silently ignored `dest_path` parameter - callers using documented single entry point were not validating the actual restore destination | `verify_integrity_and_path()` now accepts and validates `dest_path` independently; `full_restore_check()` now passes it through |
| Finding 4 (89%) | `confirm_first_run()` only checked `enabled` flag, did not verify a dry-run was actually performed | v0.11.0 adds `dry_run_token` mechanism: each dry-run generates a cryptographically random token; confirm-first-run requires a valid un-used token (24h expiry) |
| Finding 5 (88%) | Trigger phrases like "clean workspace" or "定时清理" are overly broad and can activate deletion-oriented behaviour unintentionally | Broad trigger phrases removed; only specific, unambiguous triggers like `workspace_cleaner` remain active |
| new-Finding (97%) | Non-temp files deleted just because old - users may lose valuable data | Only temp-pattern files (`_is_temp_file()` / `_is_temp_dir()`) are cleanup candidates; non-temp files explicitly skipped even if old |
| new-Finding (96%) | '临时文件清理' and '自动清理' Chinese triggers still too broad | Both removed from trigger list; only `workspace_cleaner` remains active |
| new-Finding (99%) | `_is_path_safe()` path traversal detection ineffective - `normalized=path.resolve()` always equals `resolved` | Traversal check now correctly uses parent-directory simulation to detect `..` escape; unsafe paths rejected |
| new-Finding (97%) | Documentation claimed SHA256 records provide a "signed hash" / "cryptographic signature" binding - in reality records are plain integrity checks with no authenticity guarantee against a local attacker who can modify both backup and metadata | Documentation corrected; SHA256 records accurately described as integrity checks (detect accidental modification); "signed hash" / "cryptographic signature" / "forge-resistant" claims removed throughout |
| new-Finding (91%) | `_manual_backup()` uses `shutil.copy2()` which fails silently for directories | Now handles both files (`copy2`+SHA256) and directories (`copytree`); failure returns False and blocks deletion |
---
## Changelog
### v0.11.0 (2026-05-28)
**New security audit fixes (round 2):**
- new-Finding (97%): Cleanup scope narrowed - only temp-pattern files (`_is_temp_file()` / `_is_temp_dir()`) are deletion candidates; non-temp files are always skipped regardless of age
- new-Finding (96%): Chinese triggers '临时文件清理' and '自动清理' removed; only `workspace_cleaner` activates workspace cleanup
**Previous security audit fixes:**
- Finding 1: `--force` semantics unified - SHA256 existence check bypass only
- Finding 2: `allowed_roots` default corrected to `[WORKSPACE_ROOT]`
- Finding 3: `full_restore_check()` now validates `dest_path` fully
- Finding 4: `confirm-first-run` now requires valid dry-run token
- Finding 5: Overly broad trigger phrases removed
### v0.8.1 (2026-05-27)
- workspace_cleaner disabled by default (enabled=False)
- First run requires dry-run + confirm-first-run
- Backup failure blocks deletion (skipped_backup_failed tracking)
- New commands: enable, disable, confirm-first-run
### v0.8.0
- workspace_cleaner added: scheduled temp-file cleanup with auto-backup
- 24-hour interval, 7-day expiry default
- Whitelist support
### v0.7.0
- allowed_roots defaults to workspace root
- Manifest paths HMAC-SHA256 encrypted
### v0.3.0
- SHA256 now strictly required on restore (--force for legacy)
- PATH cross-check always enforced
### v0.1.0 - v0.6.0
**DEPRECATED** - do not usedon't have the plugin yet? install it then click "run inline in claude" again.