T09 · Insecure Skill Coding Practices
- Location
scripts/stage_media.py:20- Finding
Cleanup Operation Can Delete Unrelated Files in the QQBot Relay Directory
- Content
View full analysis
None: staged = path.expanduser() if not staged.is_absolute(): staged = staged.resolve() dest_dir = DEST_DIR.resolve() staged = staged.resolve() try: staged.relative_to(dest_dir) except ValueError: raise RuntimeError(f'ERROR: refusing to delete file outside staged directory: {staged}') if not staged.exists() or not staged.is_file(): raise RuntimeError(f'ERROR: staged file not found: {staged}') staged.unlink() ``` ### Technical Analysis The cleanup function verifies only that the supplied path resolves beneath `~/.openclaw/media/qqbot/` and identifies an existing regular file. It does not verify that the file: - Was created by `stage_media.py`. - Was created for the current media-send operation. - Matches the exact output of the preceding staging command. - Is associated with an authenticated cleanup token or operation identifier. This behavior contradicts the security guarantees in `SKILL.md`, which state that cleanup is allowed only for the exact path returned by the current staging operation. Documentation-level instructions do not enforce this invariant in the executable code. The use of `Path.resolve()` and `relative_to()` prevents straightforward path traversal and resolved symlink escapes outside the relay directory. However, any unrelated regular file located inside that directory remains an accepted deletion target. ### Attack Path 1. An existing file is present under `~/.openclaw/media/qqbot/`, whether created by another send operation, another process, or the user. 2. An attacker who can influence the cleanup argument, or an erroneous caller, selects that existing file rather than the path ret ...[truncated 1056 chars]- Remediation
View remediation
