mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-11 02:33:10 +08:00
fix(hooks): allow first-time creation of protected config files
The config-protection hook blocks Write/Edit on any basename in the PROTECTED_FILES set, regardless of whether the file already exists. The hook's stated purpose is to prevent agents from softening rules in an existing config — but the same code path also blocks the legitimate bootstrap case of scaffolding a linter config into a project that has none. Add an fs.existsSync check inside run(): when the basename matches a protected entry and the file does not yet exist on disk, exit 0 and let the Write proceed. Keep the exit-2 block for all modifications to existing files. Stat errors (EACCES, etc.) fail closed — we treat the path as existing so the guard is never silently weakened. Update the existing "blocks protected config file edits" test to use a real temp file so the BLOCK path is still exercised, and add two new tests covering: - first-time creation of eslint.config.mjs is allowed (exit 0, raw passthrough, no stderr) - Edit against an existing .eslintrc.js is still blocked (exit 2, no stdout, BLOCKED message in stderr) Fixes #1873
This commit is contained in:
@@ -7,12 +7,13 @@
|
||||
* the actual code. This hook steers the agent back to fixing the source.
|
||||
*
|
||||
* Exit codes:
|
||||
* 0 = allow (not a config file)
|
||||
* 2 = block (config file modification attempted)
|
||||
* 0 = allow (not a config file, or first-time creation of one)
|
||||
* 2 = block (existing config file modification attempted)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const MAX_STDIN = 1024 * 1024;
|
||||
@@ -94,6 +95,23 @@ function run(inputOrRaw, options = {}) {
|
||||
|
||||
const basename = path.basename(filePath);
|
||||
if (PROTECTED_FILES.has(basename)) {
|
||||
// Allow first-time creation — there's no existing config to weaken.
|
||||
// The hook's purpose is blocking modifications; writing a brand-new
|
||||
// config file in a project that has none is a legitimate bootstrap
|
||||
// path (e.g. scaffolding ESLint into a fresh repo).
|
||||
let exists = false;
|
||||
try {
|
||||
exists = fs.existsSync(filePath);
|
||||
} catch {
|
||||
// Be conservative: on stat errors (EACCES, etc.) treat as existing
|
||||
// so we never silently weaken the guard.
|
||||
exists = true;
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
return { exitCode: 0 };
|
||||
}
|
||||
|
||||
return {
|
||||
exitCode: 2,
|
||||
stderr:
|
||||
|
||||
Reference in New Issue
Block a user