Proof Portal

Projects

jsonparser

ProbeLabsviewing a historical run
Viewing historical run d79405eAug 20, 2026, 03:41 PMproof-demoaudited with uncommitted changes — showing the committed treeBack to current
Back to findings
Problem reportDEFECT-260726-QS2V

Empty-string key path component panics (hazard-sweep finding)

FixedFixedHigh

This defect has been fixed and verified.

Closure: Requirement re-verified
Verified by 5 regression tests

Description

The issue as recorded. A plain-language impact summary hasn't been written for this finding yet.

A blind discovery pass (hazard-sweep for the panic_free_input_handling obligation class) found that passing "" as a path component to any of Get, GetString, GetInt, GetFloat, GetBoolean, GetUnsafeString, EachKey, Set, or Delete crashed the goroutine with runtime error: index out of range [0] with length 0 because the path-side code indexed keys[i][0] / p[level][0] without first checking that the component string was non-empty. Verified reproducers (pre-fix): Get([]byte([1,2,3]), "") // PANIC parser.go:409 (searchKeys) Get([]byte({"a":[1]}), "a", "") // PANIC parser.go:409 (searchKeys) EachKey([]byte([1,2,3]), cb, []string{""})// PANIC parser.go:614 Set([]byte({}), []byte("v"), "") // PANIC parser.go:719 (createInsertComponent) The root cause is identical in shape to the OSS-Fuzz Delete panic fixed earlier: a caller-controlled byte reaches an unguarded slice index. The fix pattern (len(...) > 0 && ...[0] == "[") already existed in Delete and has now been applied to all seven remaining dereference sites. The hazard is FIXED in this same change; the linked KnownIssue KI-260726-001 records the fixed state and the regression tests in empty_key_path_test.go.

Affected requirements

The requirement(s) this issue violates — click through to the spec.

Severity, explained

Why this is rated the way it is — and the scoring signals behind the rating (each ⓘ explains the term).

HighRated severity — the impact if this issue is exploited or hit.
risk area
Security Behavior
Security classification
Security-relevant

Where it is

The code this defect touches — peek any of these files inline to see the exact spot.

Root cause

What actually went wrong underneath — how it is classified, and the coverage gap that let it slip through.

The security/hazard-sweep role identified the same panic bug class as the OSS-Fuzz Delete panic (caller-controlled input -> unguarded `[]` index), but on the path side. Every fuzz harness hardcodes non-empty path strings, so the empty-string key component partition was never exercised. Six unguarded `keys[i][0]` / `p[level][0]` dereference sites in searchKeys, EachKey, createInsertComponent, and calcAllocateSpace panicked with `runtime error: index out of range [0] with length 0` when a caller passed an empty-string path component. The correct `len(...) > 0` guard pattern already existed in Delete (parser.go:835) but was not applied consistently to the other dereference sites.

defect class: Missing Validation
Why this escaped
Missing test partition

Disposition: Covered by a requirement

Proof it's fixed

The tests, tightened requirements and new obligations that prove this defect is gone — and can't quietly return.

Covered by a requirement.

verified by
regression tests

Blast radius

If you touch this issue, what else may need re-checking — the requirements it affects and the code and tests that hang off them. Historical view: authored trace links only — automatically derived links aren't reconstructible for past runs.

Tracing blast radius…

Touch this finding and you re-check 5 requirements · 5 code files · 23 tests.

Code files (5)
  • parser.go
  • fuzz.go
  • append.go
  • escape.go
  • path_compiler.go
Tests (23)
  • deep_spec_test.go
  • empty_key_path_test.go
  • mcdc_spec_witnesses_test.go
  • obligation_evidence_test.go
  • parser_test.go
  • sys_req_110_111_witness_test.go
  • array_each_err_test.go
  • coverage_closure_test.go
  • and 15 more

Per-requirement evidence

For each requirement this finding touches: the implementing code, verifying tests, and proof obligations that discharge it.

Implementing code (1)
  • parser.go
    Get
Tests & evidence (7)
  • README.md
  • deep_spec_test.go
  • empty_key_path_test.go
  • mcdc_spec_witnesses_test.go
  • obligation_evidence_test.go
  • parser_test.go
  • sys_req_110_111_witness_test.go
Proof obligations (3)
missing_path
  • nominal (required)obligation_evidence_test.go:217
nil_safety

Behavior specified when inputs are nil, null, or zero-value.

  • negative (required)sys_req_110_111_witness_test.go:322
  • nominal (required)sys_req_110_111_witness_test.go:214
no_path_provided
  • nominal (required)sys_req_110_111_witness_test.go:365
Implementing code (4)
  • fuzz.go
    FuzzEachKey
  • parser.go
    EachKey
  • parser.go
    EachKeyErr
  • parser.go
    sameTree
Tests & evidence (15)
  • README.md
  • array_each_err_test.go
  • coverage_closure_test.go
  • dead_code_audit_test.go
  • empty_key_path_test.go
  • fuzz_native_test.go
  • issues_56_107_229_test.go
  • mcdc_spec_witnesses_test.go
  • mcdc_supplement_test.go
  • obligation_evidence_test.go
  • parser_error_test.go
  • parser_test.go
  • path_fuzz_test.go
  • property_test.go
  • v131_regression_test.go
Proof obligations (1)
edge_case

Behavior for unusual but valid input combinations.

  • nominal (required)obligation_evidence_test.go:153
Implementing code (8)
  • append.go
    Append
  • escape.go
    SetString
  • fuzz.go
    FuzzSet
  • parser.go
    Set
  • parser.go
    WriteToBuffer
  • parser.go
    calcAllocateSpace
  • parser.go
    createInsertComponent
  • parser.go
    setConfig
Tests & evidence (15)
  • README.md
  • empty_key_path_test.go
  • escape_test.go
  • fuzz_native_test.go
  • issues_56_107_229_test.go
  • mcdc_code_supplement_test.go
  • mcdc_spec_witnesses_test.go
  • mcdc_supplement_test.go
  • obligation_evidence_test.go
  • path_compiler.go
  • path_compiler_test.go
  • property_test.go
  • reference_oracle_test.go
  • set_spec_test.go
  • v131_regression_test.go
Proof obligations (4)
boundary

Behavior at limits, thresholds, and edge-of-range values.

idempotency

Applying the operation twice produces the same result as applying once.

  • nominal (required)obligation_evidence_test.go:159
malformed_input

Behavior when inputs are syntactically or structurally invalid.

  • negative (required)set_spec_test.go:73
  • nominal (required)set_spec_test.go:11
nested_mutation
Implementing code (2)
  • parser.go
    Delete
  • parser.go
    isJSONWhitespace
Tests & evidence (7)
  • README.md
  • empty_key_path_test.go
  • mcdc_spec_witnesses_test.go
  • obligation_evidence_test.go
  • parser_test.go
  • property_test.go
  • reference_oracle_test.go
Proof obligations (2)
edge_case

Behavior for unusual but valid input combinations.

  • nominal (required)obligation_evidence_test.go:323
missing_path
  • nominal (required)obligation_evidence_test.go:324
Implementing code (2)
  • parser.go
    Delete
  • parser.go
    isJSONWhitespace
Tests & evidence (11)
  • README.md
  • deep_spec_test.go
  • empty_key_path_test.go
  • encoding_json_fuzz_test.go
  • fuzz_native_test.go
  • json_fuzz_test.go
  • mcdc_spec_witnesses_test.go
  • mcdc_supplement_test.go
  • obligation_evidence_test.go
  • path_fuzz_test.go
  • property_test.go
Proof obligations (1)
malformed_input

Behavior when inputs are syntactically or structurally invalid.

  • negative (required)obligation_evidence_test.go:335
  • nominal (required)obligation_evidence_test.go:334

Change history

Every recorded revision of this finding's source file — when it was added, edited, or re-classified, with the diff for each change.

Discussions

Discuss this with the proof team. Nothing changes in your audit automatically — you open a request and a staff member records any outcome inside the thread.

Sign in to discuss this with the proof team.Sign in