Skip to content

disk-hygiene: skill-scoped guard hook still launches via bare python3 in exec form (latent Windows fail-open) #2568

Description

@kyle-sexton

Split out of #1416 / the shell-form fix, which covered only the two wired hooks in hooks/hooks.json.

The latent defect

plugins/disk-hygiene/skills/clean/SKILL.md registers the skill-scoped belt guard in exec form:

- type: command
  command: "python3"
  args: ["${CLAUDE_PLUGIN_ROOT}/skills/clean/scripts/destructive_guard.py", "--plugin-root", "${CLAUDE_PLUGIN_ROOT}"]

Per the hooks reference, exec form resolves command as an executable on PATH, and "On Windows, exec form requires command to resolve to a real executable such as a .exe."

This plugin already documents the failure mode in its own README: on Windows python3 frequently resolves to the zero-length WindowsApps\python3.exe App Execution Alias stub. That is not a real executable, so the spawn fails — and a failed hook launch is non-blocking, so the skill-scoped guard fails open exactly like the wired ones did.

hooks/run-python-hook.sh exists precisely to solve this (it rejects the alias stub before exec-ing), but only the wired hooks route through it. The skill hook has been on bare python/python3 since #215, predating the launcher.

Why it was NOT fixed in the wired-hook PR

Not-proven-broken on the reporting host (python3 there resolves to a real 45 KB binary), while the wired hooks were proven dead. Converting a currently-working safety guard on an unverified premise risks killing a live guard — the exact harm being fixed. Deferred deliberately for a change that can be verified in a live session.

What a fix needs to establish

  1. Route the skill hook through hooks/run-python-hook.sh in shell form, mirroring the wired hooks.
  2. Confirm ${CLAUDE_PLUGIN_ROOT} substitutes for a skill-frontmatter hook in shell form. fix(disk-hygiene): stop guard hook fail-open on skill-hook data-root token #1014 found empirically that skill hooks are more restricted than documented (${CLAUDE_PLUGIN_DATA} and ${user_config.*} are unavailable and cause launch refusal). Do not add --authorized-data-rootfix(disk-hygiene): stop guard hook fail-open on skill-hook data-root token #1014 removed it for that reason.
  3. Update _skill_hook_command_and_args() in skills/clean/scripts/test_hygiene.py, which currently requires an args: line and would raise on shell form. The form-agnostic _hook_argv() helper added alongside the wired fix is the model.
  4. Verify in a live Claude Code session that the guard still blocks, since neither form is fully verifiable in CI.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions