T09 · Insecure Skill Coding Practices
- Location
scripts/sync_to_local.py:139- Finding
Unconfirmed Deletion of Local Skill Files During Synchronization
- Content
View full analysis
Vulnerability Details
File Location:
scripts/sync_to_local.py, lines 139–149
Vulnerability Type: Destructive synchronization without enforced confirmation
Risk Level: MediumVulnerable Code
python if dst.is_dir(): for root, dirs, files in os.walk(dst): dirs[:] = sorted(d for d in dirs if d not in SKIP_DIRS) rel = Path(root).relative_to(dst) for fn in sorted(files): if skip(rel, fn): continue df = Path(root) / fn if not (src_root / rel / fn).exists(): n_rm += 1 print(" [remove] %s/%s" % (name, rel / fn)) if not dry_run: try: df.unlink()Technical Analysis
The synchronization script treats every non-protected file in the destination Skill directory that is absent from the source repository as stale. Unless
--dry-runis supplied, it deletes such files usingPath.unlink().The script has a fixed protection list for selected metadata files, but it does not distinguish files previously installed by this repository from unrelated files later created or customized by the user. It also does not require an explicit deletion option, interactive confirmation, or installation manifest before removing files.
The repository’s contents determine which destination files are considered stale. Consequently, a repository author or compromised repository update can cause existing destination files to be deleted simply by omitting their corresponding source paths. There is no evidence that this behavior was implemented maliciously; it is presented as one-way synchronization, but its destructive behavior lacks a code-enforced confirmation boundary.
Attack Path
- A user has an existing installation under a target such as
~/.workbuddy/skills/hague-design-system/. - The destination contains locally added or modifi ...[truncated 1226 chars]
- A user has an existing installation under a target such as
- Remediation
View remediation
Remediation Suggestions
- Make preview mode the default and require an explicit option such as
--applybefore any filesystem changes. - Require a separate destructive option such as
--delete-stalebefore removing destination files. - Display the complete deletion list and require interactive confirmation unless a clearly named non-interactive override is supplied.
- Maintain an installation manifest recording files previously installed by this repository. Delete only manifest-owned files rather than every destination file absent from the current source.
- Preserve unknown destination files by default and report them as unmanaged.
- Offer a backup option that moves stale files into a timestamped recovery directory instead of immediately unlinking them.
- Resolve and validate the destination path before modification, ensuring it remains beneath the user-selected target and corresponds to the expected Skill directory.
- Make preview mode the default and require an explicit option such as
