Skip to content

Harden WarningRegistry against a malformed registry file#13

Open
jgamblin wants to merge 3 commits into
CVEProject:devfrom
jgamblin:harden-warning-registry
Open

Harden WarningRegistry against a malformed registry file#13
jgamblin wants to merge 3 commits into
CVEProject:devfrom
jgamblin:harden-warning-registry

Conversation

@jgamblin

Copy link
Copy Markdown

Summary

A Diagnostics result constructs a WarningRegistry (src/diagnostic/diagnostics.ts), and WarningRegistry.read() threw on unparseable or wrong-shaped registry JSON. Because validation builds a Diagnostics for every result, a corrupt warnings.json turned every validation call — including otherwise-successful ones — into a thrown exception. This makes the registry fail soft so a bad file can no longer take down validation.

This PR is a targeted robustness fix to src/registry/warnings.ts plus smoke-test coverage. No validation semantics change; behavior for a valid or missing registry is unchanged.

Changes

  • read() fails soft. On a JSON parse error or invalid shape it now warns on stderr and returns no warnings, instead of throwing. Validation is never taken down by a malformed registry file.
  • addWarning() refuses to clobber. If the existing file could not be read, addWarning() throws rather than overwriting it, so a corrupt registry's contents are never silently destroyed.
  • Warn once per corruption episode. A module-level set suppresses duplicate stderr lines (validation constructs a registry per result, so a corrupt default registry would otherwise emit one line per record). The entry is cleared on the next successful read, so a later re-corruption of the same path is reported again rather than swallowed for the process lifetime.
  • Tests (scripts/test-local.mjs): malformed JSON, valid-JSON-of-the-wrong-shape (both assert the stderr warning is surfaced), the no-clobber addWarning guard against both corrupt forms (with a byte-for-byte before/after check), and a corrupt → repair → re-corrupt recurrence test. console.warn is captured so output stays clean.

npm run test:local passes.

Notes

  • Independent of Add CI workflow and node --test suite #12 — this touches only src/registry/warnings.ts and scripts/test-local.mjs, neither of which Add CI workflow and node --test suite #12 modifies, so the two can merge in any order.
  • Accepted tradeoffs (open to feedback): the fail-soft read is whole-file (one invalid entry discards all warnings from that file), and the corruption signal is stderr rather than an in-band Diagnostics field. Both are deliberate for the fail-soft goal; happy to surface the load error programmatically instead/as well if preferred.

🤖 Generated with Claude Code

jgamblin and others added 3 commits July 21, 2026 15:17
A Diagnostics result constructs a WarningRegistry, and WarningRegistry.read
threw on unparseable or wrong-shaped registry JSON. Because validation
builds a Diagnostics for every result, a corrupt warnings.json turned every
validation call — including otherwise-successful ones — into a thrown
exception.

- read() now fails soft: on a JSON parse error or invalid shape it warns on
  stderr and returns no warnings, so validation is never taken down by a bad
  registry file.
- addWarning() refuses to run when the existing file could not be read, so a
  corrupt registry is never silently overwritten and its contents destroyed.
- Add smoke-test coverage for malformed JSON, wrong-shape content, and the
  no-clobber guard (with console.warn captured).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Warn at most once per registry path (module-level set) so a corrupt
  default registry does not emit one identical stderr line per validated
  record during batch validation.
- Tests: assert the wrong-shape case also surfaces a console.warn, and
  exercise the no-clobber addWarning guard against both malformed-JSON and
  wrong-shape files (with a byte-for-byte before/after check).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The warn-once dedupe set was never cleared, so a registry that was corrupt,
repaired, then re-corrupted within one process would silently swallow the
second corruption. Clear the dedupe entry on a successful (or missing-file)
read, so each distinct corruption episode is reported exactly once. Add a
corrupt -> repair -> re-corrupt test proving the recurrence warns again.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jgamblin jgamblin mentioned this pull request Jul 21, 2026
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