Skip to content

fix(scan): isolate --json/--markdown output during reachability analysis#1371

Open
Martin Torp (mtorp) wants to merge 1 commit into
v1.xfrom
martin/no-way-to-isolate-json-output-when-runni
Open

fix(scan): isolate --json/--markdown output during reachability analysis#1371
Martin Torp (mtorp) wants to merge 1 commit into
v1.xfrom
martin/no-way-to-isolate-json-output-when-runni

Conversation

@mtorp

@mtorp Martin Torp (mtorp) commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Problem

socket scan create --reach --json (and socket scan reach --json) cannot have its output isolated to just the JSON payload. For a non-reach scan you can do socket scan create --json 2>/dev/null, because the CLI sends all human-facing text (banner, spinner, progress, success/info/warn) to stderr and only the machine-readable result to stdout.

Reachability analysis spawned the Coana CLI with stdio: 'inherit', so Coana's progress/log output was wired straight to the parent's stdout and interleaved with the final JSON. Since 2>/dev/null only drops stderr, there was no way to get a clean JSON stream. Coana's actual result is written to a file (--socket-mode / --output-dir), so its stdout is purely diagnostic noise.

Fix

Make the Coana stdio output-kind aware:

  • text mode → 'inherit' (unchanged; Coana streams to the terminal as before).
  • json / markdown mode → ['inherit', 2, 'inherit'], which redirects the Coana child's stdout to the parent's stderr (fd 2). stdin and stderr stay inherited.

Result: in machine-readable modes the final logger.log(...) payload is alone on stdout, Coana's progress stays visible on stderr, and 2>/dev/null now isolates the JSON/markdown — matching the behavior of a non-reach scan. This is preferred over piping/capturing because it preserves real-time progress streaming.

This relies only on standard Node stdio fd-sharing, already plumbed end-to-end through the dlx launcher, local-path, and npm-install spawn paths in spawnCoanaDlx.

Changes

  • src/commands/scan/perform-reachability-analysis.mts — add outputKind option; compute the stdio and pass it to spawnCoanaDlx (replacing the hardcoded 'inherit').
  • src/commands/scan/handle-create-new-scan.mts — pass outputKind (socket scan create --reach).
  • src/commands/scan/handle-scan-reach.mts — pass outputKind (socket scan reach).
  • src/commands/scan/perform-reachability-analysis.test.mts — 4 new tests asserting stdio routing (text/default → 'inherit'; json/markdown → ['inherit', 2, 'inherit']).

Testing

  • pnpm check:tsc — clean
  • eslint on changed files — clean
  • pnpm test:unit on the reachability + both handler test files — 22/22 pass (2 pre-existing + 4 new)

Note

Low Risk
Localized change to child-process stdio wiring for reach scans; text mode unchanged and behavior is covered by new tests.

Overview
Reachability scans with --json or --markdown now keep machine-readable output on stdout only, matching non-reach scan behavior.

Coana was spawned with stdio: 'inherit', so its progress/logs went to stdout and mixed with the CLI’s final JSON/markdown. performReachabilityAnalysis now takes outputKind (default text) and passes 'inherit' in text mode or ['inherit', 2, 'inherit'] in json/markdown so Coana’s stdout is redirected to the parent’s stderr. Callers socket scan create --reach and socket scan reach forward outputKind. Four unit tests assert the stdio passed to spawnCoanaDlx.

Reviewed by Cursor Bugbot for commit 733b293. Configure here.

Reachability spawned the Coana CLI with stdio: 'inherit', so Coana's
progress/log output went to the parent's stdout and corrupted the
machine-readable payload. Since 2>/dev/null only drops stderr,
`socket scan create --reach --json` (and `socket scan reach --json`) could
not be isolated to just the JSON the way a non-reach scan can.

In json/markdown output modes, route the Coana child's stdout to the
parent's stderr (fd 2) via the stdio array ['inherit', 2, 'inherit'] so the
final JSON/markdown stays alone on stdout while progress stays visible on
stderr. Text mode keeps inheriting stdout unchanged.
@mtorp Martin Torp (mtorp) marked this pull request as ready for review June 18, 2026 11:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants