`agentshield scan` crashes with an uncaught `EISDIR` when a config root contains `.clinerules` as a directory rather than a file (Cline supports both conventions).
Repro: run `agentshield scan -p ~/.claude` in an environment where a cached Claude Code plugin (e.g. ponytail) ships `.clinerules/` as a directory of rule files.
Stack:
Error: EISDIR: illegal operation on a directory, read
at readFileSync (node:fs:484:20)
at addDiscoveredFile (dist/index.js:442:19)
at scanClaudeRoot (dist/index.js:229:7)
at discoverConfigFiles (dist/index.js:97:5)
Root cause: in `scanClaudeRoot`'s `directFiles` list, `.clinerules` is registered as a plain file and discovered via `existsSync(fullPath)` only, then passed straight to `addDiscoveredFile`, which calls `readFileSync` unconditionally. `.clinerules` is also registered in the `subdirs` list (correctly guarded with `statOrNull(dirPath)?.isDirectory()`), so the codebase already assumes it can be either — but the `directFiles` branch doesn't guard against the directory case.
Suggested fix: guard the `directFiles` loop with `statOrNull(fullPath)?.isFile()` instead of `existsSync(fullPath)`, matching the pattern already used elsewhere in the file (e.g. in `subdirs` and `discoverReferencedHookScripts`).
Env: Node v24.19.0, Windows 11, ecc-agentshield 2.2.1
`agentshield scan` crashes with an uncaught `EISDIR` when a config root contains `.clinerules` as a directory rather than a file (Cline supports both conventions).
Repro: run `agentshield scan -p ~/.claude` in an environment where a cached Claude Code plugin (e.g. ponytail) ships `.clinerules/` as a directory of rule files.
Stack:
Root cause: in `scanClaudeRoot`'s `directFiles` list, `.clinerules` is registered as a plain file and discovered via `existsSync(fullPath)` only, then passed straight to `addDiscoveredFile`, which calls `readFileSync` unconditionally. `.clinerules` is also registered in the `subdirs` list (correctly guarded with `statOrNull(dirPath)?.isDirectory()`), so the codebase already assumes it can be either — but the `directFiles` branch doesn't guard against the directory case.
Suggested fix: guard the `directFiles` loop with `statOrNull(fullPath)?.isFile()` instead of `existsSync(fullPath)`, matching the pattern already used elsewhere in the file (e.g. in `subdirs` and `discoverReferencedHookScripts`).
Env: Node v24.19.0, Windows 11, ecc-agentshield 2.2.1