Skip to content

fix(cli): --exit-code no longer fails on the URL_SCAN_LIMITED INFO note#34

Open
dmchaledev wants to merge 1 commit into
mainfrom
claude/amazing-franklin-lotlc3
Open

fix(cli): --exit-code no longer fails on the URL_SCAN_LIMITED INFO note#34
dmchaledev wants to merge 1 commit into
mainfrom
claude/amazing-franklin-lotlc3

Conversation

@dmchaledev

Copy link
Copy Markdown
Contributor

Summary

Scanning a secure https:// / wss:// endpoint with --exit-code prints PASSED but exits 1 — a false CI failure on the headline URL-scan path. This contradicts the explicit contract on the note itself in src/types.ts ("Not a vulnerability — INFO severity, never fails a gate") and the scanner test named "the URL_SCAN_LIMITED note is INFO severity and never fails the gate".

Root cause

URL mode always emits a URL_SCAN_LIMITED INFO note. The CLI exit decision in src/cli.ts counted it as a finding:

const shouldFail =
  !report.passed ||
  (exitCode && report.findings.length > 0);  // INFO note makes this always true in URL mode

So for a secure endpoint (no actionable findings, only the INFO note): report.passed === true, but exitCode && findings.length > 0 is true → exit 1.

Repro (built CLI, before fix)

$ node dist/cli.js --exit-code https://secure.example.com   # prints PASSED
$ echo $?
1

MISSING_TLS (http://) and INSECURE_TRANSPORT (ws://) are unaffected — they are real LOW+ findings and should keep failing the gate.

Fix

Extract the exit decision into a pure, side-effect-free shouldExitNonZero() in a new src/exit.ts (mirroring the existing args.ts split that keeps testable logic out of the process.exit-calling entry point). It ignores INFO-severity findings and trips the --exit-code gate only on actionable (LOW+) findings. report.passed and the --fail-on / score logic are unchanged.

Verification

secure https + --exit-code  → exit 0   (was 1)
secure wss   + --exit-code  → exit 0   (was 1)
insecure http + --exit-code → exit 1   (unchanged — MISSING_TLS)
ws           + --exit-code  → exit 1   (unchanged — INSECURE_TRANSPORT)
  • npm run lintnpm run buildnpm test ✅ — 124 passing (6 new cases in src/__tests__/exit.test.ts).

Acceptance criteria

  • --exit-code on a secure https:// / wss:// endpoint exits 0, matching the report's PASSED.
  • --exit-code still exits 1 for http:// (MISSING_TLS) and ws:// (INSECURE_TRANSPORT).
  • --exit-code still exits 1 when any actionable finding accompanies the INFO note.
  • Regression test covering the INFO-note-only case plus surrounding behavior.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WMBVioQJ2owPKgCE6aS865


Generated by Claude Code

Scanning a secure https:// / wss:// endpoint with --exit-code printed
PASSED but exited 1: the URL_SCAN_LIMITED informational note counts as a
"finding", so `exitCode && report.findings.length > 0` was always true in
URL mode. This failed CI on every secure endpoint and contradicted the
note's own documented contract ("Not a vulnerability — INFO severity,
never fails a gate").

Extract the exit decision into a pure, testable shouldExitNonZero()
(mirroring the args.ts split) that ignores INFO-severity findings and
trips the --exit-code gate only on actionable (LOW+) findings. report.passed
is unchanged. Add exit.test.ts covering the regression and the surrounding cases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WMBVioQJ2owPKgCE6aS865
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants