Skip to content

feat(fuzz): ClusterFuzzLite fuzzing of the trust-boundary parsers#58

Merged
askalf merged 1 commit into
masterfrom
feat/fuzzing
Jul 11, 2026
Merged

feat(fuzz): ClusterFuzzLite fuzzing of the trust-boundary parsers#58
askalf merged 1 commit into
masterfrom
feat/fuzzing

Conversation

@askalf

@askalf askalf commented Jul 11, 2026

Copy link
Copy Markdown
Owner

What

Adds ClusterFuzzLite continuous fuzzing of canon's three trust-boundary parsers — the hostile-input fail-safe contracts prior audit PRs established (#40 lock/gate hardening, #41 cross-OS hash, the fail-safe pass) but that nothing exercised under a fuzzer:

  • canonicalJson / sha256 (fuzz/canonical_json.fuzz.js) — never throw on circular refs, BigInt, prototype-named keys, or deeply nested junk; always return a string and a 64-hex digest.
  • gateTools (fuzz/gate_tools.fuzz.js) — never throw on a hostile tool list (non-array, null/primitive entries, __proto__/toString-named tools, duplicate-name twins) or a hostile lock entry (parts:null); always a well-formed { report, allowed:Set } with only known statuses, and never allow a content hash it did not report.
  • scanSkill (fuzz/scan_skill.fuzz.js) — never throw on a malformed skill (null, primitive, non-array scanTargets, hostile launch command); always a valid verdict whose flagged/clean state agrees with its findings.

How

  • .clusterfuzzlite/ — OSS-Fuzz JavaScript base builder + build.sh (mirrors the sibling repos' setup).
  • fuzz/ targets + a npm run fuzz local runner (fuzz/run.mjs; isolates CANON_HOME and disables the keychain defensively).
  • .github/workflows/cflite.yml — weekly (Mon 03:17 UTC) + on-demand, pinned action SHA, 300s batch, coverage sanitizer (JS has no native sanitizer).
  • @jazzer.js/core added as a fuzz-only devDependency → the package keeps zero runtime deps; files still ships only src, so nothing new is published to npm.

Validation

  • npm test: 143 tests green — the fuzz/*.fuzz.js files are not discovered by node --test.
  • npm run fuzz locally (Windows): ~215K executions across the three targets, no crashes. The gate_tools run auto-derived the __proto__/prototype dictionary, so the prototype-name duplicate-twin defense was exercised directly.

Why

Moves the OpenSSF Scorecard Fuzzing check off score 0 — one of the 6 open Scorecard advisories on the repo — matching the sibling security repos (strongroom/redstamp/fieldpass), and adds genuine hostile-input coverage of the trust boundary. No version bump.

Continuous fuzzing (Jazzer.js via ClusterFuzzLite) of canon's three
hostile-input fail-safe contracts:
  - canonicalJson / sha256: never throw on circular / BigInt / prototype-key
    input; always return a string and a 64-hex digest
  - gateTools: never throw on a hostile tool list (non-array, null/primitive
    entries, prototype-named or duplicate twins); always a well-formed
    { report, allowed:Set } with only known statuses, and never allow a hash
    it did not report
  - scanSkill: never throw on a malformed skill; always a valid verdict whose
    flagged/clean state agrees with its findings

Adds .clusterfuzzlite/ (OSS-Fuzz JS base builder + build.sh), the fuzz/
targets with a local `npm run fuzz` runner, and a weekly ClusterFuzzLite
workflow. @jazzer.js/core is a fuzz-only devDependency, so the package keeps
zero runtime deps.

Validated locally: ~215K executions across the three targets, no crashes
(the gate_tools run auto-derived the __proto__/prototype dictionary, so the
duplicate-twin defense was exercised directly). Also moves the OpenSSF
Scorecard Fuzzing check off 0, matching the sibling security repos.
@askalf
askalf merged commit fffaa1e into master Jul 11, 2026
8 checks passed
@askalf
askalf deleted the feat/fuzzing branch July 11, 2026 16:37
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