fix(scan report): render the default report as plain text instead of an object dump - #1469
Conversation
04a0c12 to
fb24f7a
Compare
|
bugbot run |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit fb24f7a. Configure here.
fb24f7a to
a020e66
Compare
|
[agent] Both red checks are pre-existing on main, not caused by this branch. Main at 0bd8b9e, which is the exact base of this PR, fails the identical set in run https://github.com/SocketDev/socket-cli/actions/runs/30843921672 — the same 4 checks, the same 129 warnings and 18 errors, and the same 1 test. Check, 4 failures, all repo-wide:
Test, 1 failure, and this one is a real bug worth its own fix: packages/cli/test/unit/commands/scan/perform-reachability-analysis-coana.test.mts reads the options bag at the wrong argument index. spawnCoanaDlx is declared as (args, options, spawnExtra) at src/util/dlx/spawn-coana.mts:53, and perform-reachability-analysis.mts:288 calls it with two arguments, so mock.calls[0][2] is undefined and reading opts.stdio throws a TypeError. Lines 315 and 327 should read mock.calls[0][1]. Run locally, both tests in that describe block fail for this reason; CI reports one because the two land in different shards. So the test has never actually asserted the stdio routing, it threw instead. Introduced by bd3f4a9, the port of #1371. None of that is fixable from inside this PR without unrelated churn, so I left it alone. |
The default `socket scan report` output went through `logger.dir()`,
Node's object inspector. In a CI log that printed a raw JavaScript
object with nested maps rendered literally, like
alerts: Map(1) { 'npm' => Map(2) { 'acme-widget' => Map(1) { ... } } }
which is hard to read in a log viewer and looks nothing like the report
the Socket GitHub App posts on a pull request.
The default text path now renders a plain-text report with labelled
sections and space-padded columns. It stays ASCII-only with no colour
and no box-drawing, because a build log may be piped to a file,
replayed without a TTY, or ingested by a log aggregator, where an
uninterpreted escape code shows up as literal noise and a non-ASCII
glyph can render as a replacement box. Each alert's URL goes on its own
indented line so a long URL cannot stretch every row past a readable
width.
`logger.dir` appeared exactly once in the whole CLI, at this call site;
every other output path already builds a string and passes it to
`logger.log`, so this brings the last outlier into line.
The new `toPlainTextReport` sits beside `toJsonReport` and
`toMarkdownReport`, and all three now read their rows from one new
`flattenReportAlerts` helper. The markdown renderer previously did that
nested-map walk inline, so sharing it means the two formats cannot
drift apart in what they show.
Only the default text output changes. The `--json`, `--markdown`, and
`--short` outputs are untouched, so anything parsing this command keeps
working as before.
Refs ASK-302.
a020e66 to
831fd78
Compare
When you run
socket scan reportin a CI/CD pipeline, the report is currently printed as a raw JavaScript object dump. NestedMapobjects show up literally, likeMap(1) { 'npm' => Map(1) { ... } }, which is hard to read in a log viewer and looks nothing like the report the Socket GitHub App posts on a pull request.This change replaces that dump with a plain-text report that has labelled sections and space-padded columns, so a reader can scan it top to bottom in a build log.
Only the default text output changes. The
--json,--markdown, and--shortoutputs are untouched, so anything that parses this command keeps working exactly as before.Refs ASK-302.
What the output looked like before, and what it looks like now — a raw object dump became a labelled report
Before, the default text path called
logger.dir(), which is Node's object inspector. For a report with two alerts it printed something close to this:After, the same report prints as:
Why the output is plain ASCII with no colour — a CI log is not a terminal
A build log is a stream of monospaced lines that may be piped to a file, replayed later without a terminal attached, or ingested by a log aggregator. Three decisions follow from that:
[32m.The columns are padded with ordinary spaces, so the table still lines up vertically wherever a monospaced font is used, which is every CI log viewer.
How the change is structured — one shared flattener now feeds both renderers
logger.dirappeared exactly once in the whole CLI, at this one call site. Every other output path already builds a formatted string and passes it tologger.log, so this brings the last outlier in line with the rest of the codebase.The new
toPlainTextReportsits alongside the existingtoJsonReportandtoMarkdownReport. All three now read their rows from one newflattenReportAlertshelper, which walks the nested ecosystem, package, and version maps and returns one flat row per alert. Previously the markdown renderer did that walk inline. Sharing it means the text and markdown reports cannot drift apart in what they show.Two small helpers do the layout:
formatLabelledPairspads theLabel:prefixes in the settings block, andformatAlertTablepads the alert columns and places each URL on its own line.Verification — 10 new tests, each one proven able to fail
The new tests assert specific properties rather than snapshotting the whole blob, so each assertion states what the contract actually is: no ANSI escapes, no characters outside printable ASCII, no raw object dump, labelled settings, health status in words, aligned columns, and a bounded line width.
Every new assertion was mutation-checked. I broke the implementation, confirmed a named test went red, then restored it:
emits no ANSI escape codesandemits only printable ASCII, so no glyph can mangle in a log viewerformatAlertTablealigns the alert columns so the table scans verticallylogger.dircall at the call siteshould handle successful result with healthy reportThe alignment test caught a real problem in its own first draft. My initial version asserted only that one character position was not a space, which still passed with the padding removed. That is a test that cannot fail for a real reason, so I rewrote it to assert that each cell begins at exactly the offset its column header begins at. The rewritten version fails when the padding is removed, as shown above.
Ran:
pnpm --filter @socketsecurity/cli run test:unit test/unit/commands/scan/— exit 1. 828 passed, 6 failed. All 6 failures are inperform-reachability-analysis.test.mtsandperform-reachability-analysis-coana.test.mts, and I confirmed the identical 6 fail on a clean default branch before making any change, so they are pre-existing and unrelated to this work.pnpm --filter @socketsecurity/cli run test:unit test/unit/commands/scan/output-scan-report-text.test.mts— exit 0. 10 passed.pnpm --filter @socketsecurity/cli run test:unit test/unit/commands/scan/output-scan-report.test.mts— exit 0. 12 passed.pnpm run lint— exit 0, "Lint passed" on the changed files.pnpm --filter @socketsecurity/cli run type— exit 0.pnpm run build:cli— exit 0.Did not run:
pnpm run check --allsuite as a gate. I did run it once on a clean default branch to record a baseline, where it exits 1 with 7 failing checks that have nothing to do with this change. I compared against that baseline rather than treating it as a pass or fail signal.Note
Low Risk
CLI presentation-only change for default text output; structured outputs and exit-code behavior are preserved and covered by updated and new unit tests.
Overview
The default
socket scan reporttext output no longer useslogger.dir()on nestedMapstructures. It now prints a plain-text policy report viatoPlainTextReport: health status, aligned settings labels, and a space-padded alert table with URLs on separate indented lines (ASCII-only, no ANSI).Shared flattening:
flattenReportAlertswalks ecosystem/package/version maps intoReportAlertRowrows; markdown (toMarkdownReport) now uses the same helper instead of duplicating the walk, so text and markdown stay aligned.--json,--markdown, and--shortpaths are unchanged. New unit tests cover the plain-text contract (no object dumps, column alignment, line width).Reviewed by Cursor Bugbot for commit fb24f7a. Configure here.