From 2fd3bd8b80eaf306179709f3d4737f28bcbd38ee Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 24 Jun 2026 05:04:55 +0000 Subject: [PATCH] fix(cli): validate URL and timeout before fetching Passing an invalid URL (e.g. `example.com` without a scheme) previously produced a cryptic `TypeError: fetch failed` from the underlying HTTP stack. Now the URL is validated with `new URL()` before the network call and a clear message is printed. Passing `--timeout abc` previously parsed to NaN and was silently ignored. Now the parsed value is validated to be a positive finite integer, and the CLI exits with an explicit error if it isn't. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01MUCfb1ic1KQVrSbgUpTpP1 --- src/cli.ts | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/cli.ts b/src/cli.ts index a6d2e8b..e0a69d1 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -80,14 +80,29 @@ async function main() { } const jsonMode = args.includes('--json'); - const timeoutArg = args.find((a, i) => a === '--timeout' && args[i + 1]); - const timeoutMs = timeoutArg ? parseInt(args[args.indexOf('--timeout') + 1], 10) : undefined; - const url = args.find(a => !a.startsWith('--') && a !== String(timeoutMs)); + const timeoutArgIdx = args.indexOf('--timeout'); + const timeoutRaw = timeoutArgIdx !== -1 ? args[timeoutArgIdx + 1] : undefined; + let timeoutMs: number | undefined; + if (timeoutRaw !== undefined) { + const parsed = parseInt(timeoutRaw, 10); + if (!Number.isFinite(parsed) || parsed <= 0) { + console.error(`Error: --timeout must be a positive integer (got "${timeoutRaw}")`); + process.exit(1); + } + timeoutMs = parsed; + } + const url = args.find(a => !a.startsWith('--') && a !== timeoutRaw); if (!url) { console.error('Usage: security-headers [--json] [--timeout ms] [--help] [--version]'); console.error('Run with --help for full usage information.'); process.exit(1); } + try { + new URL(url); + } catch { + console.error(`Error: Invalid URL "${url}". URLs must include a scheme, e.g. https://example.com`); + process.exit(1); + } try { const report = await analyze(url, timeoutMs !== undefined ? { timeoutMs } : undefined); if (jsonMode) { console.log(JSON.stringify(report, null, 2)); }