Fix: fail URL scans when the browser is unavailable (#711)

* Fix URL scan failure exit codes

Return exit 1 when browser setup or a URL scan fails, including partial multi-target scans, while preserving JSON findings output. Document the detector exit contract and cover isolated installs without Puppeteer.\n\nAI assistance disclosure: Codex implemented and tested this fix under maintainer direction.

* Fix local target failure exit codes

AI assistance disclosure: Codex implemented and tested this fix under maintainer direction.

* Handle unreadable detector targets

AI assistance disclosure: Codex implemented and tested this fix under maintainer direction.

* Report unreadable detector directories

AI assistance disclosure: Codex implemented and tested this fix under maintainer direction.
This commit is contained in:
Paul Bakaus
2026-09-02 22:19:05 -04:00
committed by GitHub
parent 1e36c86315
commit f2f9958b3d
6 changed files with 288 additions and 28 deletions
+17 -5
View File
@@ -46,15 +46,20 @@ const IMPORT_SPECIFIER_PATTERNS = [
/@(?:use|forward)\s+['"]([^'"]+)['"]/g,
];
function walkDir(dir) {
function walkDir(dir, onReadError = null) {
const files = [];
let entries;
try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return files; }
try {
entries = fs.readdirSync(dir, { withFileTypes: true });
} catch (error) {
if (onReadError) onReadError(dir, error);
return files;
}
for (const entry of entries) {
if (SKIP_DIRS.has(entry.name)) continue;
if (entry.isDirectory() && entry.name.startsWith('.') && !HIDDEN_SOURCE_DIRS.has(entry.name)) continue;
const full = path.join(dir, entry.name);
if (entry.isDirectory()) files.push(...walkDir(full));
if (entry.isDirectory()) files.push(...walkDir(full, onReadError));
else if (hasScannableExtension(entry.name)) files.push(full);
}
return files;
@@ -81,12 +86,19 @@ function resolveImport(specifier, fromDir, fileSet) {
return null;
}
function buildImportGraph(files) {
function buildImportGraph(files, onReadError = null) {
const fileSet = new Set(files);
const graph = new Map();
for (const file of files) {
const content = fs.readFileSync(file, 'utf-8');
let content;
try {
content = fs.readFileSync(file, 'utf-8');
} catch (error) {
if (!onReadError) throw error;
onReadError(file, error);
continue;
}
const dir = path.dirname(file);
const imports = new Set();