Proof Portal

Projects

jsonparser

ProbeLabs36 findings · 123 requirements
Back to findings
Problem reportDEFECT-260726-QS2V

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

FixedFixedHigh

This defect has been fixed and verified.

Verified by 5 regression tests

Introduced

When and where this issue first entered the codebase — the commit it traces back to.

Inception (latent from the first version)
Origin
Audit Finding · hazard-swe

Affected requirements

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

What this means for you

Plain-language impact — what this issue could mean for your users and your system, before any of the technical detail.

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.

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 — and how it is classified.

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

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.

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

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