Skip to content

actionlint: membership guard silently skips lint on 8.3 short paths + cd-failure reads as clean + abs-path leak in telemetry #1133

Description

@kyle-sexton

Parent

Source: handoff-inbox item 20260723-084139-actionlint-plugin-audit-findings (Findings 1, 2, 3, 6 — the silent-failure cluster; F1 reproduced Tier-0 with hand-built payloads in both path forms).

What to build

Silent-skip and silent-failure fixes in the actionlint hook (actionlint-check.sh call site — not the synced shared lib):

F1 (MED, the driver): membership guard silently skips lint on Windows 8.3 short paths. hook::read_file_path compares physical+normalized file_path against CLAUDE_PROJECT_DIR; GNU realpath under Git Bash does not expand 8.3 short names, so C:\Users\KYLESE~1\... fails the prefix match and the hook exits silently — no lint, no notice, no telemetry (exit precedes the skipped branch). Short-form paths occur in practice (Claude Code's scratchpad env var is short-form; CC does not normalize tool_input.file_path).

Producer's primary recommendation, adopt unless evidence against: remove the membership guard from this hook. PostToolUse cannot block or undo the write (hooks docs exit-code table: "PostToolUse | No | Shows stderr to Claude; the tool already ran"), so the guard protects nothing and every guard false-negative is a silent coverage loss — violating the plugin's own prerequisite-visibility doctrine ("a silently skipped feature is a defect", CHANGELOG 0.3.0). Fallback if the guard must stay: expand BOTH comparison sides via cygpath -lm on MSYS (the hook already uses cygpath -lm for FILE_REL), and make guard rejection emit the once-per-session visible skip notice instead of a bare return 1.

F2 (LOW-MED): cd failure falls through to "clean". AL_OUTPUT=$(cd "$REPO_ROOT" && actionlint ... 2>&1) || true — a failed cd yields empty output and the clean-workflow branch emits telemetry status:"ok", findings:[], indistinguishable from a real pass. Verify actionlint actually executed; emit a distinct skipped/error telemetry status on failure.

F3 (LOW): data.file can leak an absolute path. When cygpath -lm succeeds but the prefix-strip does not match (mount/symlink mismatch), FILE_REL silently stays absolute and flows into telemetry data.file, violating the schema's repo-relative contract. Degrade visibly (basename or explicit marker) rather than leaking the absolute path.

F6 (test gaps riding along): add a short-form-path regression case (suite currently leaves CLAUDE_PROJECT_DIR unset — the guard path is entirely untested); add a -pyflakes= regression fixture (only -shellcheck= is exercised; dropping -pyflakes= passes 35/35 today).

Reproduce F1 before fixing (payloads in both path forms). Verify harness claims against current official hooks docs per the repo's fresh-docs mandate.

Acceptance criteria

  • A workflow edit delivered with an 8.3 short-form file_path is linted (or, if the guard is retained, produces a visible once-per-session skip notice + telemetry) — never a silent exit
  • Failed cd/actionlint launch yields a distinct skipped/error telemetry status, never status:"ok" with empty findings
  • data.file never carries an absolute path; mismatch case degrades visibly
  • Regression tests: short-form-path case, -pyflakes= fixture; full suite passes; shellcheck clean
  • Version bump + CHANGELOG

Blocked by

None — can start immediately.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

priority: mediumReal value, no hard deadline; normal backlog flow.status: readyTriaged, unblocked, and fully specified; eligible to pick up.

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions