Install
openclaw skills install delete-recoveryAutomatically backs up files before deletion to timestamped folders, allows restoring deleted files, lists backups, and cleans expired backups and logs.
openclaw skills install delete-recovery文件误删恢复技能 v0.11.0。删除文件前先将文件备份到带时间戳的文件夹(delete_backup/YYYYMMDDHHMM/),备份时计算 SHA256 哈希并存储,恢复时验证完整性并检查路径安全(检测 ../ 等路径遍历序列)。恢复后自动删除备份(保留原始文件结构)。
v0.11.0 安全修复(针对 security audit 5项发现):
--force 语义统一文档化 - --force 仅跳过 SHA256 存在性检查;SHA256 正确性检查、PATH 跨验、遍历检测、dest_path 验证始终强制执行,不可绕过allowed_roots 默认值修正 - 从 [](无限制)改为 [WORKSPACE_ROOT](限制为 workspace 树),与文档描述一致;传入 allowed_roots=[] 可恢复无限制行为(仅用于遗留恢复)full_restore_check() 修复 - dest_path 参数不再被静默忽略,现通过 verify_integrity_and_path() 完整验证(遍历 + 与 original_path 一致性 + allowed_roots)confirm-first-run token 机制 - 每次 dry-run 生成唯一 token,确认时必须提供有效未使用的 token,防止未预览就启用的绕过workspace_cleaner 等明确触发词v0.8.1 安全修复(针对 ASI02 风险分析):
dry-run 预览并 confirm-first-run <token> 确认v0.8.0 workspace_cleaner:
dry-run 预览{workspace}/.delete_recovery/workspace_cleaner/,技能删除后配置仍保留v0.7.0 安全加固:
allowed_roots 默认为 workspace 根目录 - 恢复目标限制在 {workspace} 树内,防止恢复文件到任意路径manifest.jsonl 中⚠️ 版本说明: v0.1.0~v0.6.0 已淘汰(DEPRECATED),功能说明保留仅供参考。请始终使用 v0.7.0 或更高版本。
触发词: 删除文件、误删恢复、恢复文件、查看备份、清理备份、验证备份完整性、搜索已删除文件、检索删除记录、workspace_cleaner
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:
--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.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.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.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.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.
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
{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 存在性检查--force 绕过{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> 需要提供有效且未使用的 tokendry-run 获取新 token{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).--force. Never use --force unless you understand the backup predates v0.3.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 |
npm i -g clawhubclawhub login# 通过 ClawHub 安装技能
clawhub install delete-recovery
# 查看已安装的技能
clawhub list
npm i -g clawhubclawhub login# Install skill via ClawHub
clawhub install delete-recovery
# List installed skills
clawhub list
所有命令通过执行脚本实现,路径:
{workspace}/skills/delete-recovery/scripts/delete_recovery.py
python delete_recovery.py backup <file_path> [original_path] [description]
file_path:要备份的文件完整路径original_path(可选):原始文件路径,恢复时用于定位,默认为 file_pathdescription(可选):功能简介,建议 ≤6 字,如"飞书配置""工作报告",默认为文件名备份时自动计算并存储 SHA256 哈希 + 原始路径到 .sha256 文件,防止备份文件被替换。备份后自动将(文件名、功能简介、路径)写入 manifest.jsonl,支持 search 检索。
返回示例:
{"ok": true, "folder": "202603261130", "file": "C__Users__user__Desktop__test.txt", "description": "工作报告"}
python delete_recovery.py search <keyword>
在 manifest.jsonl 中按文件名、功能简介或路径关键字模糊搜索,返回匹配的备份位置和恢复命令。
keyword:检索关键词(大小写不敏感, substring 匹配)返回示例:
{
"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
}
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),任一验证失败均拒绝恢复。
返回示例:
{"ok": true, "restored_to": "C:\\Users\\user\\Desktop\\test.txt", "backup_deleted": true}
python delete_recovery.py verify <backup_folder> <safe_name>
在不恢复的情况下验证备份完整性(SHA256 哈希匹配 + PATH 交叉验证)。
python delete_recovery.py list
返回所有备份文件夹列表,最新在前。
python delete_recovery.py delete_backup <folder>
删除指定的备份文件夹(同时清理 manifest 索引)。
python delete_recovery.py cleanup
立即执行过期备份(7天)和日志(30天)全量清理,忽略时间触发限制。
python delete_recovery.py log [lines]
查看最近 N 行操作日志(默认50行)。
v0.11.0 首次启用流程(必须按顺序):
# 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 文件) |
python workspace_cleaner.py status
Shows: enabled flag, first-run confirmed flag, current token status, interval, expiry days.
# 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
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 24 # every 24 hours
python workspace_cleaner.py set-expire-days 7 # files older than 7 days
backup,防止误删temp_existing/ 目录--keep-backup 可保留\、/、: 替换为 __,恢复时需使用转换后的名称cleanup 命令本身不受影响,仍立即执行全量清理restore --force 可强制恢复(仅跳过 SHA256 存在性检查;完整性、PATH、dest_path 验证不可绕过)backup 自动追加索引,restore 成功后自动剔除;过期备份文件夹对应的索引随 cleanup 或脚本启动时自动清理allowed_roots=[].path 文件负责enable 命令显式启用;首次运行需先 dry-run + token confirm-first-runskipped_backup_failedworkspace_cleaner 等明确触发词有效backup before any deletiontemp_existing/ before restoring--keep-backup to retain\, /, : replaced with __ in backup filenamescleanup command itself still runs full cleanup immediatelyrestore --force to force restore (only bypasses SHA256 existence check; integrity, PATH, dest_path validation non-bypassable)backup auto-indexes; restore auto-removes index entry; stale entries pruned on cleanup or script startupallowed_roots=[] to restore outside workspace (legacy restores only).path file in the backup folderenabled defaults to False; must explicitly enable; first run requires dry-run + token confirm-first-runskipped_backup_failedworkspace_cleaner are active| 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 |
New security audit fixes (round 2):
_is_temp_file() / _is_temp_dir()) are deletion candidates; non-temp files are always skipped regardless of ageworkspace_cleaner activates workspace cleanupPrevious security audit fixes:
--force semantics unified - SHA256 existence check bypass onlyallowed_roots default corrected to [WORKSPACE_ROOT]full_restore_check() now validates dest_path fullyconfirm-first-run now requires valid dry-run tokenDEPRECATED - do not use