feat(tests): add fuzz harnesses, threat model & hash scoping (roadmap 11.5) - #45
Merged
Merged
Conversation
… 11.5) Close the review's security gap for the untrusted-input components. Fuzzing: one libFuzzer harness each for JsonParser, CliParser, and BinaryDeserializer under src/fuzz/, gated by EGL_UTIL_BUILD_FUZZERS with a `fuzz` preset (Clang/libFuzzer, ASan+UBSan) and a CI smoke job. Each is dual-mode: a real LLVMFuzzerTestOneInput, plus a standalone replay main (fuzz_standalone.hpp) when not built with libFuzzer — so the whole matrix (incl. MSVC) compiles them, they stay in the clang-tidy compile database, and a crashing corpus entry replays locally. The libFuzzer uint8_t* ABI is bridged to string_view/span cast-free (no reinterpret_cast, no raw pointer arithmetic) to stay tidy-clean without NOLINT. The asserted invariant: never crash, never UB, never throw on input. Threat model: docs/security/threat-model.md documents the trust boundary, each component's attack surface + mitigations, and the fuzzing strategy; linked from SECURITY.md and spec §6. Hash scoping: hash.hpp now states the NON-cryptographic scope explicitly (SHA-256 is an integrity digest, not constant-time, not for passwords/MACs/signatures) — correcting the prior "the cryptographic digest" wording — with a @warning on sha256(). Extended NIST FIPS 180-4 vectors: the 56-byte two-block message (static_assert) and the one-million-'a' message (runtime). Local verify (MSVC): util_tests 221/221 green incl. the new SHA-256 vectors; standalone harnesses build and replay clean; clang-format and clang-tidy clean on the new sources; consistency_lint passing. libFuzzer mode itself is CI-only (no Clang on the dev box). ADR-0031 Co-Authored-By: Claude Opus 4.8 (1M context) <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.
Summary
Closes the review's security gap: a threat model, libFuzzer harnesses for the three
untrusted-input components, and an explicit non-cryptographic scope for the hash functions
(with extended NIST vectors). The one Milestone-11 item with a code component.
Motivation
Spec-review acceptance criterion: "A security section covers untrusted-input parsing and
hash-function scoping, with enumerated fuzzing targets and SHA-256 test-vector validation."
Roadmap item 11.5. Decision locked with the maintainer: SHA-256 is non-cryptographic.
Changes
src/fuzz/cpp/it/d4np/util/): one libFuzzer harness each forJsonParser,CliParser,BinaryDeserializer, gated byEGL_UTIL_BUILD_FUZZERS, with afuzzpreset(Clang/libFuzzer + ASan/UBSan) and a CI
fuzzsmoke job (bounded-max_total_time).LLVMFuzzerTestOneInput, plus a standalone replaymain(
fuzz_standalone.hpp) when not built with libFuzzer — so the whole matrix (incl. MSVC)compiles them, they stay in the clang-tidy compile DB, and a crashing input replays locally.
docs/security/threat-model.md): trust boundary, per-component attack surfaceSECURITY.mdand spec §6.hash.hpp): states the non-cryptographic scope (integrity digest, notconstant-time, not for passwords/MACs/signatures) + a
@warningonsha256()— correcting theprior "the cryptographic digest" wording. Extended NIST FIPS 180-4 vectors: the 56-byte
two-block message (
static_assert) and the one-million-'a'message (runtime).Design Patterns
Verification
util_tests221/221 green incl. the new SHA-256 vectors (compile-timestatic_assert+ runtime); all three standalone harnesses build and replay clean onsample JSON / argv / binary input.
clang-formatandclang-tidyclean on the new sources (tidy: the libFuzzeruint8_t*ABIis bridged cast-free — no
reinterpret_cast, no raw pointer arithmetic, noNOLINT).python tools/consistency_lint.pypasses.new
fuzzCI job are unverified locally; the harness logic is exercised via standalone replay.Documentation Impact
SECURITY.md+ newdocs/security/feat