mirror of
https://github.com/Jeuners/ECC.git
synced 2026-09-09 23:12:30 +02:00
On a case-insensitive filesystem (macOS APFS/HFS+, Windows NTFS) a write to `.ESLINTRC.JS` lands on the exact same inode as `.eslintrc.js`, but the guard looked the basename up in PROTECTED_FILES with a case-sensitive `Set.has`. Every entry in that Set is lowercase, so any case-variant path missed the branch entirely and returned exit 0 — a single Write silently overwrote a live config while the hook reported success. Reproduced on macOS APFS: `.eslintrc.js` and `.ESLINTRC.JS` share one inode, yet the hook returned exit 2 for the former and exit 0 for the latter, and the uppercase write replaced the real config's contents. This is a one-step bypass of the whole guard and needs no shell access, unlike the known delete-then-recreate route. Fix: also test `basename.toLowerCase()`. All 32 PROTECTED_FILES entries are already lowercase, so the fallback is exact. On a genuinely case-sensitive filesystem this costs at most a false positive on a distinct file whose name differs from a protected one by case alone. Behaviour deliberately unchanged: first-time creation is still allowed (the bootstrap affordance), non-config paths still pass through, and the existing lstat/ENOENT fail-closed semantics are untouched. Test: adds a case-variant case that asserts exit 2. It guards itself with an inode comparison and skips on case-sensitive filesystems rather than asserting something untrue there. Verified in both directions — it FAILS against the unpatched hook (`Got 0; 0 !== 2`) and passes with the fix. Suite: 9/9. |
||
|---|---|---|
| .. | ||
| auto-tmux-dev.test.js | ||
| bash-hook-dispatcher.test.js | ||
| block-no-verify.test.js | ||
| check-hook-enabled.test.js | ||
| config-protection.test.js | ||
| continuous-learning-observe-runner.test.js | ||
| continuous-learning-shebang-consistency.test.js | ||
| cost-tracker.test.js | ||
| cursor-block-no-verify.test.js | ||
| design-quality-check.test.js | ||
| detect-project-worktree.test.js | ||
| doc-file-warning.test.js | ||
| ecc-context-monitor.test.js | ||
| ecc-metrics-bridge.test.js | ||
| ecc-statusline.test.js | ||
| evaluate-session.test.js | ||
| gateguard-fact-force.test.js | ||
| governance-capture.test.js | ||
| hook-flags.test.js | ||
| hooks.test.js | ||
| insaits-security-monitor.test.js | ||
| insaits-security-wrapper.test.js | ||
| mcp-health-check.test.js | ||
| migrate-homunculus-home-escape.test.js | ||
| observe-entrypoint-allowlist.test.js | ||
| observe-signal-counter-race.test.js | ||
| observe-signal-timeout.test.js | ||
| observe-subdirectory-detection.test.js | ||
| observer-loop-archive.test.js | ||
| observer-loop-mktemp.test.js | ||
| observer-memory.test.js | ||
| plan-canvas-sessions-hook.test.js | ||
| plugin-hook-bootstrap.test.js | ||
| post-bash-hooks.test.js | ||
| posttooluse-dispatcher.test.js | ||
| pre-bash-commit-quality.test.js | ||
| pre-bash-dev-server-block.test.js | ||
| pre-bash-reminders.test.js | ||
| pre-bash-tmux-reminder.test.js | ||
| quality-gate.test.js | ||
| run-with-flags-truncation.test.js | ||
| session-activity-tracker.test.js | ||
| session-end.test.js | ||
| stop-format-typecheck.test.js | ||
| stop-hooks-stdout.test.js | ||
| suggest-compact.test.js | ||
| test_insaits_security_monitor.py | ||