Fuzz hardening: hostile YAML, the Windows path alphabet, loud corruption - #375
Merged
Conversation
…h alphabet, store corruption
Gold plan step 2. Three hardenings, each with the invariant that hostile input
produces a rejection WITH A REASON — never a hang, a blowup, an unhandled
exception, or a silently skipped record.
YamlGuard (both loaders, pre-parse):
- anchors/aliases rejected outright. YamlDotNet expands aliases, so a tiny
document can be crafted to expand exponentially (billion-laughs); ashlar
documents never need aliases, so none are accepted. The scan is textual and
deliberately a little eager; honest prose ampersands survive (tested).
- 1MB size cap. Configuration, not cargo.
Proposal ids: ALLOWLIST replaces the blocklist. The old check blocked / \ . and
admitted the entire Windows hazard alphabet — trailing dots/spaces (Win32 strips
them, so two ids collide and append-once is bypassed), ':' (NTFS alternate data
streams), unicode confusables. Now: ^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$ plus an
explicit Win32 reserved-name deny (CON/NUL/PRN/AUX/COM*/LPT*) on EVERY OS — a
store written on Linux with a CON.json breaks when it syncs to Windows, so the
same ids are legal everywhere. The reserved-name case was caught by this very
suite: the first allowlist passed CON because it is perfectly alphanumeric — the
fuzz tests corrected their own author before shipping.
Store corruption fails CLOSED and LOUD: ListAsync used to silently skip records
that deserialized to null and let JsonException escape raw. A corrupt HELD record
silently vanishing from the queue is an invisible pending decision — the worst
failure shape an admission store can have. Reads now surface a Corrupt-gate-record
error naming the file; a store that cannot be fully read is a store this class
refuses to summarize.
37 tests: alias bomb (rejected in <2s, before expansion), oversize, six
garbage/type-confusion shapes against both loaders with no escaping exceptions,
21 hostile ids, 4 legitimate ids, truncated and null records.
Verified: kernel build 0/0, Tests.Kernel 303/303, cert gate 178.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Gold plan step 2 (sheet 10.2). Three hardenings, one invariant: hostile input gets a rejection with a reason — never a hang, an expansion blowup, an escaped exception, or a silently skipped record.
37 new tests. Tests.Kernel 303/303 · cert gate 178 · kernel build 0/0.
🤖 Generated with Claude Code