Skip to content

Add cve-validate CLI#14

Open
jgamblin wants to merge 3 commits into
CVEProject:devfrom
jgamblin:add-cli
Open

Add cve-validate CLI#14
jgamblin wants to merge 3 commits into
CVEProject:devfrom
jgamblin:add-cli

Conversation

@jgamblin

Copy link
Copy Markdown

Summary

Adds a cve-validate command so CVE Records and CNA Containers can be validated from the shell or a CI pipeline, without writing a script against the library API. This is one of the more commonly requested additions. It wraps the existing Validate API — no validation logic changes.

Usage

cve-validate record.json                       # validate a file
cve-validate record1.json record2.json         # validate several
cat record.json | cve-validate                 # read from stdin (or "-")
cve-validate --type published-cna container.json
cve-validate --type rejected-cna  container.json
cve-validate --json record.json                # machine-readable output
  • --type record|published-cna|rejected-cna (default record)
  • --json, -q/--quiet, -h/--help, -v/--version, and -- end-of-options
  • Exit codes: 0 all valid, 1 any invalid or unreadable, 2 usage error
  • Registry warnings are printed under each result and reflected in the summary count
  • Human output uses ✓/✗/⚠ on UTF-8 terminals and falls back to PASS/FAIL/WARN otherwise
  • Errors and usage go to stderr; results go to stdout, so --json … | jq is clean

Changes

  • src/cli.ts — the CLI (arg parsing, file/stdin input, dispatch to the three Validate methods, human/JSON output).
  • package.jsonbin: cve-validate → dist/cli.js, build src/cli.ts alongside src/index.ts, add a test:cli script.
  • scripts/test-cli.mjs — spawn-based tests covering valid/invalid/mixed inputs, --json, stdin (- and piped), --quiet, all three --type values and the --type= form, --help/--version (asserting the real package version), short flags, --, unknown option, bad --type, missing file, malformed JSON, a packaging guard (asserts src//dist/ stay in files and the bin path), and a slow-pipe truncation regression test.
  • README.md — CLI section.

Notes

  • Exit handling: the entrypoint sets process.exitCode rather than calling process.exit(), so buffered stdout drains before exit — otherwise large --json output is truncated at the OS pipe buffer when piped to another process. The regression test reproduces this with a backpressured slow reader.
  • Packaging: the published bin resolves its schema/registry JSON assets from src/ at runtime, so src/ must remain in the package files allowlist (it is today; a test guards this).
  • Independent of Add CI workflow and node --test suite #12 and Harden WarningRegistry against a malformed registry file #13 — new files plus additive package.json/README edits in distinct regions, so all three merge in any order.
  • Follow-up (out of scope): a top-level null record input currently surfaces a raw TypeError string rather than a clean FAILED_JSON_SCHEMA_VALIDATION; the root cause is the input guard in src/core/validate.ts, best fixed there separately.

🤖 Generated with Claude Code

jgamblin and others added 3 commits July 21, 2026 16:09
Adds a `cve-validate` bin for validating CVE Records and CNA Containers from
the shell or a CI pipeline, wrapping the existing Validate API.

- src/cli.ts: parse args, read one or more JSON files (or stdin via `-` / a
  pipe), validate as record (default) or published-cna / rejected-cna via
  --type, and print human-readable or --json output. Exit 0 (all valid),
  1 (any invalid or unreadable), 2 (usage error). Supports --help/--version.
- package.json: add the `bin`, build src/cli.ts alongside src/index.ts, add a
  `test:cli` script.
- scripts/test-cli.mjs: spawn the built CLI and assert output + exit codes
  across valid/invalid/mixed inputs, --json, stdin, --quiet, --type, --help,
  --version, unknown option, bad type, missing file, and malformed JSON.
- README: document the CLI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Surface registered warnings in default human output (previously only in
  --json): print each warning under its result and include a count in the
  summary; document it in the README.
- ASCII fallback for the status glyphs on non-UTF-8 (legacy Windows) consoles.
- Guard the entrypoint with a top-level catch so any unexpected failure
  (e.g. an unreadable manifest in --version) exits with a code instead of an
  unhandled rejection.
- Tests: lock stdout/stderr separation (empty stderr on success/--json, empty
  stdout on usage errors), assert warnings are populated (length + messageId)
  in both JSON and human output, make --version non-vacuous, and cover short
  flags, --type= form, rejected-cna, the '--' separator, detail lines, and a
  packaging guard that src/ and dist/ stay in the published files.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Round-2 review found a high-severity defect: the entrypoint called
process.exit(code) as soon as run() resolved, terminating before async
stdout writes to a pipe had drained. Large output (e.g. --json over many
files) was truncated at the ~64KB OS pipe buffer, making piped JSON
unparseable and silently dropping validation results.

- Set process.exitCode instead of calling process.exit(), so the event loop
  drains stdout before exiting (both the .then and .catch branches).
- Add a slow-pipe regression test that produces >64KB of output, consumes it
  with backpressure, and asserts the full payload parses (proven to fail on
  the old process.exit path).
- Count only warnings that are actually printed toward the summary, so the
  --quiet count matches visible output.
- Make the quiet assertion match the per-file marker directly instead of a
  fragile /valid$/m that also matches "invalid".

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant