Skip to content

feat: report incomplete scan data with diagnostics#893

Open
luojiyin1987 wants to merge 26 commits into
OWASP:mainfrom
luojiyin1987:feat/output-report-incomplete-scan-data
Open

feat: report incomplete scan data with diagnostics#893
luojiyin1987 wants to merge 26 commits into
OWASP:mainfrom
luojiyin1987:feat/output-report-incomplete-scan-data

Conversation

@luojiyin1987

@luojiyin1987 luojiyin1987 commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

Review note

This PR introduces a new scan completeness model and touches multiple parts of the pipeline.

I realize the current change is larger than a typical feature PR because the completeness information needs to flow from the scanner layer to all output formats.

This is an initial implementation of the design. If maintainers prefer, I am happy to split this PR into smaller focused changes:

  1. Introduce ScanCompleteness data model and scanner tracking
  2. Add CLI / JSON / HTML reporting support
  3. Add ratchet baseline handling for incomplete detection data

Feedback on architecture and scope is welcome before merging.

Summary

Introduce scan completeness tracking to report when scan results may be incomplete.

Previously, CVE Lite CLI only reported detected vulnerabilities. However, a scan result with no findings does not always mean "no vulnerabilities exist" — some vulnerability data or remediation metadata may be unavailable during scanning.

This PR introduces ScanCompleteness as first-class metadata attached to scan results, allowing users and CI systems to distinguish:

  • No vulnerabilities detected
  • Vulnerabilities could not be fully evaluated due to incomplete scan data

Design

Problem

Security scanners must avoid creating false confidence.

For example:

Dependency scan
        |
        +-- OSV advisory lookup failed
        |
        +-- No findings returned

The result should not be interpreted as:

No vulnerabilities found

because the scan may not have had enough information to make a complete determination.

At the same time, not all failures have the same impact:

  • Some failures may affect vulnerability detection
  • Some failures only affect remediation guidance

Therefore, scan completeness needs to track both the occurrence and impact of incomplete data.


Solution

A scan result now contains:

ScanResult
├── findings
│   └── detected vulnerabilities
│
└── completeness
    └── diagnostics describing scan confidence

ScanCompleteness does not replace vulnerability findings.

It describes the confidence level of the scan process and whether additional investigation is needed.

Diagnostics are classified by impact:

Detection impact
    |
    +-- May cause missed vulnerabilities

Remediation impact
    |
    +-- May cause missing or incomplete fix recommendations

Tracked incomplete scan scenarios

Detection impact

These conditions may affect vulnerability discovery:

Diagnostic Description
OSV detail transient failure Advisory detail lookup failed temporarily
Offline advisory missing Advisory record is unavailable in local database
Confirmed missing OSV record Finding references an advisory without available detail data

Detection-impact issues prevent trusted baseline creation because incomplete detection data could hide future vulnerabilities.


Remediation impact

These conditions affect fix recommendations only:

Diagnostic Description
Packument fetch failure Package metadata unavailable for remediation
Remediation failure Upgrade recommendation generation failed
Chain resolution failure Validated upgrade path could not be resolved

Remediation-only issues do not block baseline operations because vulnerability findings remain reliable.


Output changes

Completeness information is propagated through all report formats:

Scanner
   |
   +-- CLI output
   |
   +-- Compact output
   |
   +-- JSON output
   |
   +-- HTML report
   |
   +-- Multi-folder report

Users can see:

  • Whether scan data is complete
  • What caused incomplete results
  • Whether the issue affects detection or remediation

Example:

⚠ Scan data is incomplete

Some vulnerability findings may be incomplete because:
- 2 advisory detail lookups failed with transient errors

or:

⚠ Scan data is incomplete

Vulnerability findings are available, but remediation guidance may be incomplete:

- 3 transitive remediation attempts failed across 2 packages

Baseline / ratchet behavior

Baseline files represent trusted detection results.

Creating or evaluating a baseline from incomplete detection data could silently hide vulnerabilities.

Therefore:

Detection-impact diagnostic
        |
        v
Refuse baseline create/evaluation

However:

Remediation-only diagnostic
        |
        v
Allow baseline operation with warning

This keeps ratchet behavior strict for vulnerability detection while avoiding unnecessary failures for remediation-only issues.


Implementation changes

Scanner

  • scanPackages now returns:
{
  findings,
  completeness
}
  • Added tracking for:

    • OSV detail failures
    • Offline missing records
    • Confirmed missing advisory records
    • Packument failures
    • Remediation failures
    • Chain resolution failures

Types

Added:

  • ScanDiagnostic
  • ScanDiagnosticCode
  • ScanCompleteness

Output

Updated:

  • CLI printers
  • Compact output
  • JSON writer
  • HTML reporter
  • Multi-folder reports

to display completeness diagnostics.


Tests

Updated affected tests covering:

  • Scanner completeness tracking
  • Diagnostic generation
  • Output rendering
  • Multi-folder reports
  • Ratchet baseline behavior

Why this approach

A scan result should communicate not only:

What vulnerabilities were found?

but also:

How confident are we that the scan had enough information to make that determination?

ScanCompleteness provides this confidence layer while keeping vulnerability findings and remediation recommendations separate.

Changes

  • scanner.tsscanPackages now returns { findings, completeness }; six failure scenarios are tracked and built into ScanCompleteness
  • types.ts — add ScanDiagnostic, ScanDiagnosticCode, ScanCompleteness types
  • printers.tsprintFinalStatus / printCompactOutput accept completeness param; new printIncompleteDiagnostics prints yellow diagnostics banner
  • html-reporter.ts — add completeness-banner CSS + renderCompletenessBanner to show warnings in HTML reports
  • write-outputs.ts — pass completeness to JSON output (adds status, complete, diagnostics)
  • index.ts — plumb completeness through scan → output pipeline
  • multi-folder-scan.ts — adapt to new scanPackages return signature
  • Tests updated for all affected modules

Track scan completeness by capturing transient OSV detail failures,
offline missing records, packument fetch errors, remediation failures,
and chain resolution failures. Surface diagnostic warnings in CLI output,
HTML report banner, and JSON output when scan data may be incomplete.
@luojiyin1987
luojiyin1987 requested a review from sonukapoor as a code owner July 25, 2026 03:29
@luojiyin1987
luojiyin1987 marked this pull request as draft July 25, 2026 03:33
…nd reporting

- Pass completeness to writeOutputs call site so JSON output receives
  real scan completeness instead of always reporting ok/complete
- Add onTransientFailure callback to fetchPackument so scanner can
  track packument failures that were previously silently caught
- Add completeness field to MultiFolderScanResult and propagate
  through multi-folder printer, JSON output, and HTML reports
- Add aggregateMultiFolderCompleteness to deduplicate diagnostics
  across subfolders when aggregating counts
- Fix compact mode zero-findings early return that skipped the
  incomplete scan warning
- Differentiate HTML completeness banner text by diagnostic impact:
  detection failures vs remediation-only failures
- Fix HTML banner diagRows join using literal backslash-n
- Make ScanState.completeness required to prevent silent downgrades
…h all paths

- Pass onTransientFailure callback through resolvePublishedFixVersion,
  resolveLowestKnownNonVulnerableVersion, validateDirectFixTargets, and
  resolveChainFix so direct-only scans also track registry failures
- Fix printFinalStatus zero-findings path to show incomplete warning
  instead of conflicting green success when scan data is incomplete
- Export renderCompletenessBanner and add per-folder + aggregate
  completeness banners to multi-folder HTML reports
- Update footer text from 'Re-run the scan' to 'Resolve the issues
  above and re-run the scan'
…ckument tracking

- Add module-level RegistryFetchObserver with onTransientFailure and
  onSuccess callbacks, set by scanner via setRegistryFetchObserver
- All fetchPackument calls through any remediation path now
  automatically track transient failures and clear on retry success
- Remove duplicate inline completeness aggregation in HTML reporter;
  use shared aggregateMultiFolderCompleteness from multi-folder-scan
- Fix aggregateMultiFolderCompleteness to update message text
  when merging diagnostic counts
- Fix verbose mode printFinalStatus to show 'Partial scan:' prefix
  instead of conflicting 'Scan complete' when data is incomplete
…formatDiagnosticMessage

- Rename onSuccess to onResolved in RegistryFetchObserver and call it
  on 404 responses too, so transient-failure-then-404 retries clear
  old failure entries
- Export formatDiagnosticMessage from scanner and use it in
  aggregateMultiFolderCompleteness instead of regex replacement
  for correct pluralization in merged diagnostic messages

test: add observer retry tests and multi-folder aggregation tests
…agnostics

- Replace manual message construction with formatDiagnosticMessage calls
  so single-folder and multi-folder aggregation share one message source
- Update PACKUMENT_FETCH_FAILURE message: 'transitive remediation' ->
  'remediation guidance' since it now covers direct fix validation too
@luojiyin1987
luojiyin1987 marked this pull request as ready for review July 25, 2026 07:27
- Remove onTransientFailure callback from fetchPackument and all
  downstream functions (resolvePublishedFixVersion, resolveLowest...,
  resolveChainFix, traceChain, validateDirectFixTargets).
  RegistryFetchObserver handles all tracking now.
- Compress buildCompletenessDiagnostics: extract inner push() helper
  to eliminate five repeated diagnostic-construction blocks.
- Simplify printFinalStatus: single 'incomplete' flag drives all
  three branches, collapsing duplicate conditional branches.
…recedence

- Rename push() to addDiagnostic() with early-return guard and
  expanded object literal for readability
- Restore redBright for Partial scan with critical/high findings
  by branching renderStatus on urgent flag
@luojiyin1987
luojiyin1987 force-pushed the feat/output-report-incomplete-scan-data branch from a2dd5af to 51a0b0f Compare July 25, 2026 07:46
@luojiyin1987
luojiyin1987 marked this pull request as draft July 25, 2026 11:35
@luojiyin1987

Copy link
Copy Markdown
Collaborator Author

The remaining Self Scan failures are unrelated to this PR.

Both findings come from Jest's transitive development dependencies:

  • jest -> glob -> minimatch -> brace-expansion@2.1.2
  • jest -> babel-plugin-istanbul -> test-exclude -> minimatch -> brace-expansion@1.1.16

I also tried upgrading Jest from 30.4.1 to 30.4.2, but the affected dependency paths remain because Jest still depends on the same glob, minimatch, and test-exclude versions.

The regular CI and CodeQL checks pass, and the Self Scan jobs complete successfully before exiting with code 1 due to --fail-on high.

Since these are pre-existing, dev-only transitive dependency findings and are outside the scope of this PR, I am not changing the Self Scan policy, adding overrides, or expanding this PR further. The dependency issue can be handled separately once upstream packages provide compatible fixes.

@luojiyin1987
luojiyin1987 force-pushed the feat/output-report-incomplete-scan-data branch from 7fe2efb to 84bd6ae Compare July 25, 2026 16:59
@luojiyin1987
luojiyin1987 marked this pull request as ready for review July 25, 2026 17:34
@luojiyin1987

Copy link
Copy Markdown
Collaborator Author

This PR introduces scan completeness tracking as a foundational model. It intentionally wires the model through all output channels.

@sonukapoor

Copy link
Copy Markdown
Collaborator

Thanks for this @luojiyin1987 - the ScanCompleteness model is a genuinely nice piece of design, and I appreciate you flagging the size and offering to split it. Let's take you up on that: three focused PRs would be much easier to review and land one at a time - roughly (1) the core ScanCompleteness model + scanner threading, (2) the output surfaces (terminal/JSON/HTML/multi-folder), and (3) the ratchet/baseline gating. CI is green here so there is no rush on that front - it is purely about review-ability. And #898 makes sense as the follow-up once this infrastructure lands. Thank you!

@luojiyin1987

Copy link
Copy Markdown
Collaborator Author

Thanks for the clear direction and for the positive feedback on the ScanCompleteness design.

I’ll split the current implementation into three focused PRs:

  1. Core ScanCompleteness model and scanner threading
  2. Output surfaces: terminal, JSON, HTML, and multi-folder reports
  3. Ratchet/baseline gating behavior

I’ll keep each PR focused and make the dependency between them clear. I’ll also leave #898 as a separate follow-up after this infrastructure has landed.

I’ll update this PR with links to the split PRs once they are ready. Thanks!

@sonukapoor

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