fix: handle EPERM/EACCES in scanForLeakedPaths on Windows (#1055)

Wrap readdirSync and readFileSync calls in try/catch to silently skip
directories and files with restricted ACLs (e.g. Chrome/Gemini certificate
stores on Windows) instead of crashing the installer.

Closes #964

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
TÂCHES
2026-03-15 11:39:47 -06:00
committed by GitHub
parent 0b8e2d2ef2
commit e5b389cdb1

View File

@@ -2432,13 +2432,29 @@ function install(isGlobal, runtime = 'claude') {
const leakedPaths = [];
function scanForLeakedPaths(dir) {
if (!fs.existsSync(dir)) return;
const entries = fs.readdirSync(dir, { withFileTypes: true });
let entries;
try {
entries = fs.readdirSync(dir, { withFileTypes: true });
} catch (err) {
if (err.code === 'EPERM' || err.code === 'EACCES') {
return; // skip inaccessible directories
}
throw err;
}
for (const entry of entries) {
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
scanForLeakedPaths(fullPath);
} else if ((entry.name.endsWith('.md') || entry.name.endsWith('.toml')) && entry.name !== 'CHANGELOG.md') {
const content = fs.readFileSync(fullPath, 'utf8');
let content;
try {
content = fs.readFileSync(fullPath, 'utf8');
} catch (err) {
if (err.code === 'EPERM' || err.code === 'EACCES') {
continue; // skip inaccessible files
}
throw err;
}
const matches = content.match(/(?:~|\$HOME)\/\.claude\b/g);
if (matches) {
leakedPaths.push({ file: fullPath.replace(targetDir + '/', ''), count: matches.length });