Generated by Proof — the verification layer for AI-assisted development and continuous correctness audit.
Verdict: Net positive: 6 issue(s) resolved and none introduced this release.
| Signal | Count | Detail |
|---|---|---|
| ✅ Resolved this cycle | 6 | — |
| 🔴 Introduced this release (still open) | 0 | 0 regression + 0 net-new |
| 🟥 …of which HIGH-severity | 0 | — |
| 📋 Pre-existing backlog (gated, reproduced) | 10 | — |
⚠️ no –from given: report is a point-in-time snapshot; every artifact is treated as in-range
Rows are non-overlapping: every open KnownIssue is counted exactly once — either as introduced this release (regression + net-new) or in the pre-existing still-open backlog.
| Bucket | Count |
|---|---|
| KnownIssues resolved this cycle | 6 |
| Defects introduced this release (0 regression + 0 net-new) | 0 |
| Pre-existing still-open backlog | 10 |
| Historical coverage backfill (fixed before baseline; not in window) | 0 |
| Accepted risks (active) | 0 |
Corpus totals: 16 KnownIssues, 8 ProblemReports.
Issues we previously reported to you that this release fixes — verified by tripwire tests that now pass.
| KI | Severity | Resolved | Fixing ref | Title |
|---|---|---|---|---|
KI-1 |
🟧 HIGH | 2026-07-26T13:14:18Z | — | Empty-string key path component panics in searchKeys/EachKey/createInsertComponent/calcAllocateSpace |
KI-15 |
🟨 MEDIUM | 2026-08-03T12:00:00Z | — | decodeUnicodeEscape lone low surrogate \uDC00 is substituted with U+FFFD instead of a bogus code point |
KI-16 |
🟩 LOW | 2026-08-03T12:00:00Z | — | Delete with no key path returns an empty, non-aliasing slice (root-delete contract) |
KI-2 |
🟩 LOW | 2026-07-29T06:33:00Z | — | ParseInt("-") returns (0, nil) — silent false-success on sign-only input |
KI-3 |
🟧 HIGH | 2026-07-27T00:00:00Z | — | Set with array-index path component under an object parent produces malformed JSON output |
KI-4 |
🟨 MEDIUM | 2026-07-29T06:33:00Z | — | Set on top-level array-index beyond length returns KeyPathNotFoundError instead of appending |
The audit’s headline finding: bugs whose introducing change lands inside this window (snapshot) and that are STILL OPEN at HEAD. 0 qualify: 0 regression and 0 net-new. Each is also tracked as an open known issue and carries a committed reproducer; its introducing commit is linked below.
No regressions introduced this release.
No net-new defects introduced this release.
Additionally, 0 defect-tracked regression(s) and 6 defect-tracked net-new defect(s) are detailed in sections 4 and 5 below.
Issues still present in this release, each gated to a requirement and reproduced.
10 active KnownIssues total — all listed individually below. Severity (holistic across all dimensions) and CVSS (security-only score from the source vector) render as separate columns, so a MEDIUM correctness item is not lost behind a HIGH security item.
| KI | Status | Severity | CVSS | Age | Title |
|---|---|---|---|---|---|
KI-11 |
open | 🟧 HIGH | 7.5 High | since inception | ParseBoolean uses prefix match instead of exact equality — “trueish”/“falsehood” accepted as booleans |
KI-5 |
open | 🟧 HIGH | 7.5 High | since inception | decodeSingleUnicodeEscape length guard too small — OOB read + panic on a truncated \uXX escape |
KI-6 |
open | 🟧 HIGH | 7.5 High | since inception | unescapeToUTF8Config length guard off-by-one — OOB panic reading in[1] on a lone trailing backslash |
KI-7 |
open | 🟧 HIGH | 7.5 High | since inception | parseInt fast-path threshold off-by-one — 19-digit integers skip overflow check and wrap silently |
KI-8 |
open | 🟧 HIGH | 7.5 High | since inception | decodeUnicodeEscape lone-high-surrogate guard reads in[6]/in[7] with a too-small length check — OOB panic |
KI-10 |
open | 🟨 MEDIUM | 5.3 Medium | since inception | arrayEachConfig empty-array sentinel checks for ‘}’ instead of ‘]’ — a valid [] is rejected as malformed |
KI-9 |
open | 🟨 MEDIUM | 5.3 Medium | since inception | h2I upper-hex bound off-by-one — byte ‘G’ decodes as hex 16, so \uGxxx is silently accepted |
KI-13 |
open | 🟩 LOW | 3.7 Low | since inception | nextTokenConfig drops the tab from its whitespace set — parsing fails on tab-formatted JSON |
KI-14 |
open | 🟩 LOW | 3.7 Low | since inception | unescapeToUTF8Config drops ‘/’ from the accepted escapes — the valid JSON escape \/ is rejected as malformed |
KI-12 |
open | ⬜ — | — | since inception | arrayEachConfig empty-input guard returns the wrong documented error type (MalformedJsonError vs MalformedObjectError) |
Behavior that was correct in the baseline and broke within this window — verified against git history (the introducing commit is inside the audited range).
No defect-tracked regressions in this window.
Defects whose introducing commit lands inside this window (or, for findings with no commit, found by this audit) and that are not regressions of previously-correct behavior.
DEFECT-260726-3F95 — ParseInt("-") returns (0, nil) — silent false-success on sign-only input
DEFECT-260726-MFPA — Set with array-index path component under an object parent produces malformed JSON output (silent corruption)
DEFECT-260726-QS2V — Empty-string key path component panics (hazard-sweep finding)
DEFECT-260727-ARR1 — ArrayEach on non-array root emitted spurious callback before erroring
DEFECT-260727-T7P7 — Set on top-level array-index beyond length returns KeyPathNotFoundError (SYS-REQ-110 contract gap)
DEFECT-260727-WWWY — Set beyond-length array index on scalar array destroys all elements (SYS-REQ-110 violation)
(internal) Bugs both introduced AND fixed before the baseline — not in the audited window. Listed only to record the coverage (requirement + tripwire) this audit added so they cannot silently regress.
These bugs were both introduced and fixed before the baseline — this release did not introduce them and they are not in the audited window; listed here only to record the coverage (requirement + tripwire) this audit added so they cannot silently regress.
No historical-backfill defects in scope.
Requirements graded by their worst-case consequence per obligation class, severity-descending. Each row pairs an authored consequence (or a catalog-generic fallback, marked) with the class it grades. Consequence severity is authored — the catalog cannot silently promote or demote a project’s judgment.
| REQ | Class | Severity | Rollup | Consequence |
|---|---|---|---|---|
SYS-REQ-017 |
malformed_input | critical | critical | Get on adversarial input like {“a”: (no value token) drives nextToken to return -1; an unguarded data[i] dereference in the value classification step panics with index-out-of-range on network-reachable input. |
SYS-REQ-029 |
malformed_input | critical | critical | ArrayEach on adversarial input like [1,{ drives nextToken past EOF; an unguarded i+1 increment in the iteration loop panics with index-out-of-range on network-reachable input. |
SYS-REQ-035 |
malformed_input | critical | critical | Delete on adversarial input like ,{“test”:1{}} drives findTokenStart/tokenEnd to stale offsets; the unguarded data[prevTok] dereference (parser.go:907) panics with index-out-of-range — the OSS-Fuzz witness shape. |
SYS-REQ-041 |
truncated_at_value_boundary | critical | critical | Get on {“a”:1 (no closing brace) drives tokenEnd to return len(data); an unguarded data[end+1] dereference or array-index use of the sentinel panics with index-out-of-range. |
SYS-REQ-042 |
truncated_mid_structure | critical | critical | Get on {“a”:[1,2 (unclosed array) drives the recursion in findKeyStart past EOF; an unchecked data[i] dereference in the value-offset read panics with index-out-of-range. |
SYS-REQ-043 |
truncated_mid_key | critical | critical | Get on {“a (unclosed key string) drives stringEnd to return -1; the unguarded break leaves i past EOF and a subsequent data[i] dereference panics with index-out-of-range. |
SYS-REQ-048 |
truncated_at_value_boundary | critical | critical | Delete on {“a”:1 (the PR-truncation witness) drives internalGet to return stale offsets; the cleanup path slices data[:start] + data[end:] with end > len(data) and panics with slice-out-of-range. |
SYS-REQ-049 |
error_propagation | critical | critical | Delete discards the internalGet error and proceeds with stale offsets into data[prevTok]/data[end:] (parser.go:907), panicking with index-out-of-range on adversarial input — the OSS-Fuzz witness shape. |
SYS-REQ-052 |
callback_error_propagation | critical | critical | ArrayEach silently continues iteration after a Get error returns a stale (value,offset) pair; the next loop iteration dereferences data[offset] past EOF, panicking with index-out-of-range. |
SYS-REQ-053 |
truncated_mid_element | critical | critical | ArrayEach on [1,{“a”: (truncated second element) advances i past EOF in the next iteration; an unchecked data[i] peek of the comma/delimiter panics with index-out-of-range. |
SYS-REQ-056 |
truncated_mid_structure | critical | critical | Delete on {“a”:{“b”:1 (unclosed nested object) drives findKeyStart into recursion that over-reads; the cleanup data[prevTok] dereference at parser.go:907 panics with index-out-of-range. |
SYS-REQ-057 |
partial_literal | critical | critical | ParseBoolean on a 3-byte tru over-reads 4 bytes past EOF checking for the true/false literal, panicking with index-out-of-range on a buffer that is exactly 3 bytes long. |
SYS-REQ-060 |
truncated_escape_sequence | critical | critical | ParseString on a token like \u00 (truncated unicode escape) reads 4 hex digits past EOF in the hex-decode loop, panicking with index-out-of-range or producing a corrupt rune. |
SYS-REQ-071 |
malformed_input | critical | critical | GetString on adversarial input where Get returns an error discards the error and calls ParseString on a stale value slice, panicking with index-out-of-range in the unescape step. |
SYS-REQ-072 |
truncated_escape_sequence | critical | critical | GetString on a value like “\u00 reads 4 hex digits past EOF in ParseString’s hex-decode loop, panicking with index-out-of-range or returning a corrupt rune to the caller. |
SYS-REQ-075 |
malformed_input | critical | critical | GetInt on adversarial input where Get returns an error discards the error and calls ParseInt on a stale or nil slice, returning a wrong int64 or panicking with index-out-of-range. |
SYS-REQ-079 |
partial_literal | critical | critical | GetBoolean on an addressed token like tru (3 bytes) over-reads 4 bytes past the literal check in ParseBoolean, panicking with index-out-of-range or returning a wrong bool to the caller. |
SYS-REQ-080 |
malformed_input | critical | critical | GetUnsafeString on adversarial input where Get returns an error discards the error and returns a stale raw slice past EOF; the caller reads out-of-range bytes and panics in the unescape path. |
SYS-REQ-082 |
truncated_at_value_boundary | critical | critical | GetUnsafeString on {“a”: (truncated value) propagates a stale offset from Get; the returned slice points past EOF and the caller’s bytes access traverses out-of-range memory. |
SYS-REQ-083 |
truncated_at_value_boundary | critical | critical | ArrayEach on [1, (truncated array at value boundary) advances i to EOF and the next loop body dereferences data[i] to peek the next delimiter, panicking with index-out-of-range. |
SYS-REQ-084 |
truncated_mid_structure | critical | critical | ObjectEach on {“a”:1 (unclosed object) recurses past EOF in findKeyStart; the value-offset read at data[i] panics with index-out-of-range on the truncated input. |
SYS-REQ-085 |
sentinel_value_boundary | critical | critical | EachKeys uses the tokenEnd sentinel len(data) as an array index into data[] during multi-path scan (e.g. data[tokenEnd(offset)]), panicking with index-out-of-range instead of returning -1. |
SYS-REQ-029 |
non_array_root_no_callback | medium | critical | ArrayEach on a non-array root value (object, number, bool, null) without a key path invoked the callback ONCE with the first content token misinterpreted as an array element (e.g. an object key parsed as a string element), then returned MalformedArrayError. A caller performing side effects in the callback observed a spurious invocation on input that is not an array at all. Fixed in DEFECT-260727-ARR1; regression test TestArrayEachNonArrayRootNoCallback_SYS029 locks all non-array root type partitions. |
SYS-REQ-082 |
edge_case | low | critical | GetUnsafeString on a 1-byte truncated value returns a wrong-length raw slice that points past the value boundary, corrupting downstream byte math. |
STK-REQ-001 |
empty_input | high | high | Get on a zero-length []byte drives internalGet nextToken to -1; the subsequent data[offset] dereference in getType panics with index-out-of-range on the empty slice. |
STK-REQ-001 |
malformed_input | high | high | Adversarial JSON like {“a”:,} drives searchKeys data[i] dereference on a delimiter with no following value, replicating the OSS-Fuzz Delete panic class on Get. |
STK-REQ-001 |
negative_array_index | high | high | Path [-1] parses to aIdx=-1 via strconv.Atoi with no sign check; the curIdx match never fires and stale valueOffset arithmetic can panic on stale-offset dereference. |
STK-REQ-001 |
nil_safety | high | high | Get(nil) flows into searchKeys; nextToken on the nil slice returns -1 and getType(nil,0) data[offset] dereference panics with nil-slice index-out-of-range. |
STK-REQ-001 |
sentinel_value_boundary | high | high | When searchKeys/blockEnd/nextToken return the -1 sentinel for not-found, internalGet/ArrayEach dereference data[offset] without re-checking offset>=0 (the OSS-Fuzz Delete panic class). |
STK-REQ-001 |
truncated_at_value_boundary | high | high | Payload like {“a”: with no value drives nextToken to -1 on the remainder; the subsequent data[offset] dereference in getType panics with index-out-of-range. |
STK-REQ-001 |
truncated_mid_key | high | high | Payload like {“key with no closing quote drives stringEnd to -1; if the break guard regresses, searchKeys continues and dereferences data[i] past len(data), crashing the process. |
STK-REQ-001 |
truncated_mid_structure | high | high | Payload like {“a”:[1,2 with no matching close bracket drives blockEnd to -1; if the return-check regresses the unbounded loop dereferences past the buffer end, crashing the parser. |
STK-REQ-002 |
empty_input | high | high | GetString on a zero-length []byte drives Get to internalGet to nextToken=-1; the follow-on getType dereference panics with index-out-of-range on the empty slice. |
STK-REQ-002 |
encoding_safety | high | high | Malformed UTF-8 inside a JSON string value (lone continuation byte) is passed through Unescape without normalization; the returned Go string contains invalid UTF-8, corrupting downstream string operations. |
STK-REQ-002 |
malformed_input | high | high | Adversarial JSON like {“k”:”\q”} drives Unescape to MalformedStringEscapeError; if error propagation regresses, GetString returns a corrupt decoded string or panics on the bad escape offset. |
STK-REQ-002 |
nil_safety | high | high | GetString(nil, …) flows straight through Get to internalGet to searchKeys nil-slice loop; getType(nil,0) data[offset] dereference panics with nil-slice index-out-of-range. |
STK-REQ-002 |
truncated_escape_sequence | high | high | Truncated \u escape at end of string (“abc\u31”) drives Unescape hex-digit scan past the buffer end; if the bounds check regresses the parser reads past len(data) and panics with slice-bounds error. |
STK-REQ-003 |
empty_input | high | high | GetInt on a zero-length []byte flows through Get empty-input path; the data[offset] dereference in getType panics with index-out-of-range on the empty slice. |
STK-REQ-003 |
malformed_input | high | high | GetInt on a token like 12x34 drives parseInt to ok=false; if the malformed check regresses, GetInt silently returns 12 (the partial parse) instead of MalformedValueError. |
STK-REQ-003 |
nil_safety | high | high | GetBoolean(nil, …) flows through Get nil-slice path; getType(nil,0) data[offset] dereference panics with nil-slice index-out-of-range. |
STK-REQ-003 |
partial_literal | high | high | GetBoolean on a truncated tru or fals token fails bytes.Equal against the literal; if the partial-literal recovery regresses the caller path panics on the empty value slice. |
STK-REQ-004 |
callback_error_propagation | high | high | If ObjectEach/ArrayEach swallow a callback returned error and continue iterating, the next iteration invokes the callback on stale offset state, corrupting traversal and dereferencing past the buffer end. |
STK-REQ-004 |
empty_input | high | high | ArrayEach on a zero-length []byte returns MalformedObjectError via the early guard; if the guard regresses nextToken returns -1 and the follow-on data[offset] dereference panics on the empty slice. |
STK-REQ-004 |
malformed_input | high | high | ArrayEach on adversarial JSON like [1,2,,] drives Get to a parse error mid-array; if the error-propagation guard regresses the loop continues past the malformed token and dereferences data[offset] past len(data). |
STK-REQ-004 |
nil_safety | high | high | ObjectEach(nil,…) flows through searchKeys nil-slice loop; the subsequent nextToken/data[offset] dereference panics with nil-slice index-out-of-range. |
STK-REQ-004 |
sentinel_value_boundary | high | high | When searchKeys or blockEnd returns -1 sentinel for malformed structure, ArrayEach/EachKey dereference data[offset] without re-checking offset>=0 (the OSS-Fuzz Delete panic class). |
STK-REQ-004 |
truncated_at_value_boundary | high | high | Truncated JSON like [1,2 with no closing bracket drives nextToken in ArrayEach to -1; the follow-on data[offset] dereference panics with index-out-of-range on the truncated remainder. |
STK-REQ-004 |
truncated_mid_element | high | high | Truncated JSON like [1,“abc with no closing string mid-element drives Get to stringEnd returning -1; the follow-on data[offset] dereference in ArrayEach panics past the buffer end. |
STK-REQ-004 |
truncated_mid_structure | high | high | Truncated JSON like {“a”:[1,2 with no matching close bracket drives blockEnd to -1; if the guard regresses the unbounded loop dereferences past the buffer end, crashing the process. |
STK-REQ-005 |
empty_input | high | high | Set on a zero-length []byte drives internalGet to nextToken=-1; if the empty-input guard regresses the follow-on data[firstToken] dereference panics on the empty slice. |
STK-REQ-005 |
error_propagation | high | high | Set internalGet returns an error on malformed input; if the error check regresses Set continues with stale startOffset/endOffset=-1 and slices data[:-1] or panics on the negative offset. |
STK-REQ-005 |
malformed_input | high | high | Delete on adversarial JSON like {“a”:,} drives findKeyStart/tokenEnd to stale offsets; if guards regress the data[endOffset+tokEnd] dereference panics (OSS-Fuzz 4649128545288192 class). |
STK-REQ-005 |
nil_safety | high | high | Delete(nil,…) drives internalGet to searchKeys nil-slice loop; the follow-on tokenEnd/findTokenStart/data[prevTok] dereference panics on the nil slice. |
STK-REQ-005 |
no_path_provided | high | high | Set/Delete with zero keys must return early; if the early-return guard regresses the next data[keys[lk-1][0]] dereference panics on the empty keys slice with index-out-of-range. |
STK-REQ-005 |
sentinel_value_boundary | high | high | When internalGet/searchKeys return -1 sentinel for not-found, Delete tokenEnd/findTokenStart arithmetic dereferences data[endOffset+tokEnd] without bounds re-check (the OSS-Fuzz 4649128545288192 panic class). |
STK-REQ-005 |
truncated_at_value_boundary | high | high | Delete on payload like {“a”: with no value drives internalGet to error; if the error guard regresses Delete continues with stale offsets and the data[endOffset+tokEnd] dereference panics on the truncated slice. |
STK-REQ-005 |
truncated_mid_structure | high | high | Delete on payload like {“a”:[1,2 with no closing bracket drives blockEnd to -1; if the guard regresses the unguarded data[endOffset+tokEnd] dereference panics past the buffer end. |
STK-REQ-006 |
empty_input | high | high | GetUnsafeString on a zero-length []byte flows through Get to internalGet to nextToken=-1; the follow-on data[offset] dereference in getType panics on the empty slice. |
STK-REQ-006 |
malformed_input | high | high | GetUnsafeString on adversarial JSON like {“k”:} drives Get to searchKeys returning a stale offset; the follow-on data[offset] dereference panics (the OSS-Fuzz bug class on the unsafe path). |
STK-REQ-006 |
nil_safety | high | high | GetUnsafeString(nil,…) flows through Get to searchKeys nil-slice loop; getType(nil,0) data[offset] dereference panics with nil-slice index-out-of-range. |
STK-REQ-006 |
truncated_at_value_boundary | high | high | Payload like {“k”:“abc with no closing quote drives stringEnd to -1; if the guard regresses getType data[offset] dereference panics past the buffer end on the unsafe string path. |
STK-REQ-007 |
encoding_safety | high | high | ParseString on a JSON string containing invalid UTF-8 bytes passes them through Unescape; the returned Go string contains invalid UTF-8, corrupting downstream rendering and string operations. |
STK-REQ-007 |
nil_safety | high | high | ParseString(nil) flows into Unescape(b, stackbuf[:]); the b[i] dereference inside Unescape panics with nil-slice index-out-of-range on the nil token. |
STK-REQ-007 |
partial_literal | high | high | ParseBoolean on a truncated tru or fals token fails bytes.Equal and returns MalformedValueError; a regression in the partial-literal check feeds the truncated bytes to a downstream consumer that panics on the short slice. |
STK-REQ-007 |
truncated_escape_sequence | high | high | ParseString on a token ending in a truncated u-escape like abc\u31 drives Unescape hex-digit scan past the token end; if the bounds check regresses the parser reads past len(b) and panics. |
SYS-REQ-002 |
encoding_safety | high | high | GetString on a body containing invalid UTF-8 (e.g. a lone surrogate like \uDDDD) returns a Go string with invalid runes; the caller re-serializes it as invalid JSON or panics in encoding-aware downstream. |
SYS-REQ-009 |
boundary | high | high | Set on an array-index path component [N] where N >= len(array) silently overwrites element 0 or another existing element the caller did not address, destroying data and returning a mutated document with no error (PR #286 regression class). |
SYS-REQ-009 |
malformed_input | high | high | Set with an array-index path component [N] whose parent in the addressed JSON is an OBJECT (or vice-versa) emits malformed JSON output and returns it with nil error (DEFECT-260726-MFPA / KI-3); the caller has no signal that the returned bytes are unparseable. |
SYS-REQ-010 |
malformed_input | high | high | Delete on a well-formed array/object with whitespace between the deleted element and the trailing comma (or the close bracket) leaves a dangling comma or close-bracket sequence in the output, producing malformed JSON the caller cannot re-parse (DEFECT-260726-3PSJ, found by FuzzPathMutation). |
SYS-REQ-010 |
nil_safety | high | high | Delete on nil data panics in nextToken at data[0] instead of returning the empty document, crashing the caller on a nil trust-boundary input. |
SYS-REQ-014 |
encoding_safety | high | high | ParseString on a raw body containing a malformed UTF-8 sequence (e.g. a lone surrogate) returns a Go string with invalid runes; the caller re-serializes it as invalid JSON or panics in encoding-aware downstream like bufio. |
SYS-REQ-015 |
nil_safety | high | high | ParseInt on a nil slice panics with index-out-of-range at data[0] in the first-byte classification instead of returning MalformedValueError. |
SYS-REQ-016 |
nil_safety | high | high | An empty-string key component flowing into searchKeys on nil-or-zero-length internal slices triggers an unguarded keys[i][0] / p[level][0] dereference, crashing the goroutine (OSS-Fuzz 4649128545288192 panic class, SYS-REQ-111 hazard). |
SYS-REQ-016 |
no_path_provided | high | high | An empty-string key component is structurally a no-effective-path case; if the early guard regresses the keys[i][0] dereference panics with index-out-of-range on the empty component slice (SYS-REQ-111 hazard class). |
SYS-REQ-019 |
nil_safety | high | high | Get on nil data panics in nextToken at data[0] instead of returning NotExist with KeyPathNotFoundError, crashing the caller on a nil trust-boundary input. |
SYS-REQ-028 |
nil_safety | high | high | ArrayEach on nil data panics in nextToken at data[0] instead of returning without invoking the callback, crashing the caller on a nil trust-boundary input. |
SYS-REQ-036 |
malformed_input | high | high | ParseBoolean on adversarial input like truN over-reads past the literal check and returns true, misclassifying malformed input as a valid boolean and corrupting downstream control flow. |
SYS-REQ-039 |
boundary | high | high | ParseInt on 99999999999999999999 silently wraps via strconv to a negative int64 (ignoring ErrRange), producing a wrong-sign value at the caller. |
SYS-REQ-044 |
sentinel_value_boundary | high | high | A caller of tokenEnd uses the returned len(data) sentinel as data[end] rather than treating it as EOF (e.g. value classification peeks data[tokenEnd(…)] for the next delimiter), panicking with index-out-of-range. |
SYS-REQ-047 |
negative_array_index | high | high | Get on path [-1] is parsed by strconv.Atoi as -1 and then used as data[i-1] or an array element index, wrapping to a large unsigned index and panicking with index-out-of-range. |
SYS-REQ-074 |
nil_safety | high | high | GetString on nil data panics in nextToken at data[0] instead of returning the not-found result, crashing the caller on a nil trust-boundary input. |
SYS-REQ-076 |
boundary | high | high | GetInt on 99999999999999999999 silently wraps via strconv to a negative int64 (ignoring ErrRange), producing a wrong-sign value at the caller. |
SYS-REQ-078 |
nil_safety | high | high | GetInt on nil data panics in nextToken at data[0] instead of returning the not-found result, crashing the caller on a nil trust-boundary input. |
SYS-REQ-081 |
nil_safety | high | high | GetUnsafeString on nil data panics in nextToken at data[0] instead of returning the not-found result, crashing the caller on a nil trust-boundary input. |
SYS-REQ-110 |
boundary | high | high | Set on [len(array)] or beyond silently overwrites element 0 (or another existing element the caller did not address), destroying data and returning a mutated document with no error — silent corruption of unaddressed state. |
SYS-REQ-110 |
element_type_partition | high | high | Set on a beyond-length array index under a nested key whose existing array contains SCALAR first elements (numbers, strings, bools, nulls, nested arrays — anything where the first element byte is not ‘{’) silently replaces the entire array with a single-element [value], destroying all existing data. The append-at-end code path’s guard previously required data[subObjOff]==’{’ , so only object-first-element arrays took the append branch; scalar arrays fell through to the replace-container branch. Fixed in DEFECT-260727-WWWY; regression test TestSetBeyondLengthScalarArrayPreservesElements_SYS110 locks all scalar element-type partitions. |
SYS-REQ-111 |
missing_path | high | high | An empty-string key component reaches an unguarded keys[i][0] / p[level][0] dereference and panics with runtime error: index out of range [0] with length 0 (the OSS-Fuzz 4649128545288192 / hazard-sweep class, DEFECT-260726-QS2V, KI-1), crashing the goroutine on caller-controlled input. |
SYS-REQ-111 |
nil_safety | high | high | An empty-string key component flowing into searchKeys/EachKey/createInsertComponent on nil-or-zero-length internal slices triggers an unguarded index dereference, crashing the goroutine (the OSS-Fuzz 4649128545288192 panic class). |
SYS-REQ-111 |
no_path_provided | high | high | An empty-string key component is structurally a no-effective-path case; if the early guard regresses the keys[i][0] dereference panics with index-out-of-range on the empty component slice. |
SYS-REQ-112 |
malformed_input | high | high | A non-container addressed value (scalar, mismatched bracket) or a missing path returns a silent zero count or a wrong error type (e.g. nil instead of MalformedArrayError / KeyPathNotFoundError), hiding the lookup failure from the caller. |
SYS-REQ-113 |
boundary | high | high | A [*] component matching an empty array regresses to invoke the callback once with a stale value, or SetWildcard corrupts the document on the empty-match no-op path; multi-wildcard composition drops one branch of the cartesian product. |
SYS-REQ-113 |
malformed_input | high | high | A [*] component addressing a non-array container (object, scalar) is not rejected with MalformedArrayError and instead panics, silently skips, or mutates an unaddressed sibling; nested malformed JSON inside a matched element propagates incorrectly to the caller. |
SYS-REQ-114 |
malformed_input | high | high | An unbalanced bracket, missing key between dots, control character in a quoted key, or non-numeric bracket index other than * is accepted as a parsed component instead of returning errMalformedPath / errUnterminatedKey, producing a path slice that silently fails to resolve downstream or crashes searchKeys. |
SYS-REQ-116 |
malformed_input | high | high | A truncated string, array, or object is treated as complete and yielded to the caller, or the parser loops forever waiting for a delimiter after stream EOF. |
STK-REQ-001 |
boundary | medium | high | Value at exactly len(data) makes tokenEnd return len(data); an omitted bounds check slices data[offset:endOffset] past the buffer end and panics with index-out-of-range. |
STK-REQ-001 |
determinism | medium | high | lastMatched state in searchKeys leaks across sibling object keys, so two Get calls on identical []byte can resolve to different value slices for the same path. |
STK-REQ-001 |
edge_case | medium | high | Get on a bare scalar payload (“null”/“true”) with no key path regresses the no-keys fast path to return an empty slice or wrong ValueType instead of the scalar bytes. |
STK-REQ-001 |
idempotency | medium | high | Returned value slice aliases the input buffer via value[:len(value):len(value)]; a caller mutating the buffer between calls sees the prior Get result silently change. |
STK-REQ-001 |
missing_path | medium | high | A stale valueFound from a prior sibling match in the same call leaves Get returning a wrong-key byte slice instead of KeyPathNotFoundError, silently corrupting downstream decoding. |
STK-REQ-001 |
type_mismatch | medium | high | Get on a JSON String where the caller expected Number returns quoted bytes; strconv.ParseInt on the quoted token silently returns 0 instead of an explicit type error. |
STK-REQ-002 |
determinism | medium | high | Two GetString calls on identical input must return byte-identical Go strings; a regression in the Unescape path (surrogate-pair handling diverging between stack and heap allocations) produces different decoded output. |
STK-REQ-002 |
edge_case | medium | high | GetString on an empty JSON string value (””) regresses to returning NullValueError or an empty slice instead of the empty Go string, breaking the empty-string boundary. |
STK-REQ-002 |
type_mismatch | medium | high | GetString on a JSON Number or Boolean returns the documented type error or silently coerces the raw bytes; callers expecting a string field read garbage from a numeric value. |
STK-REQ-003 |
boundary | medium | high | GetInt on int64.MaxInt64+1 silently wraps via parseInt overflow flag; if the overflow check regresses, GetInt returns a negative int64 instead of OverflowIntegerError. |
STK-REQ-003 |
determinism | medium | high | ParseFloat on the same numeric token must return the same float64 across calls; a regression in parseFloat rounding direction (architecture-dependent FPU) produces non-deterministic results. |
STK-REQ-003 |
edge_case | medium | high | GetBoolean on a payload with value null returns NullValueError instead of (false,nil); callers treating the zero-value as absent silently misread null fields as boolean false. |
STK-REQ-003 |
type_mismatch | medium | high | GetInt on a JSON String value returns the documented not-a-number error; if the type check regresses, GetInt feeds raw quoted bytes to ParseInt which silently returns 0 instead of erroring. |
STK-REQ-004 |
determinism | medium | high | EachKey callback order on identical input must be deterministic; a regression in pathFlags match order produces callbacks in different order across calls, breaking deterministic processing. |
STK-REQ-004 |
edge_case | medium | high | ArrayEach on a single-element array must invoke the callback exactly once; a regression in the post-callback offset arithmetic invokes it twice or zero times, breaking the count contract. |
STK-REQ-005 |
edge_case | medium | high | Set on a payload where the target path parent is an empty object must insert with comma=false; a regression inserts a leading comma, producing invalid JSON output downstream. |
STK-REQ-005 |
idempotency | medium | high | Delete applied twice to the same path must produce the same output as Delete once; a regression in the trailing-comma cleanup leaves a stray comma on the second call, corrupting the mutated payload. |
STK-REQ-005 |
missing_path | medium | high | Delete for a non-existent key must return the original payload unchanged; a regression in findKeyStart KeyPathNotFoundError handling leaves Delete mutating an arbitrary sibling position. |
STK-REQ-005 |
nested_mutation | medium | high | Set on a deeply nested path (a.b.c.d) drives createInsertComponent to emit nested object scaffolding; a regression in calcAllocateSpace under-allocates the buffer and WriteToBuffer writes past the end. |
STK-REQ-006 |
determinism | medium | high | Two GetUnsafeString calls on identical input must return byte-identical Go strings via bytesToString; a regression in slice aliasing produces non-deterministic content if the input buffer is concurrently mutated. |
STK-REQ-006 |
edge_case | medium | high | GetUnsafeString on a payload with value empty-string must return the empty Go string; a regression in the String-strip path returns the surrounding quotes as part of the value. |
STK-REQ-007 |
boundary | medium | high | ParseInt on input like 9223372036854775808 (int64 max+1) must return OverflowIntegerError; if parseInt overflow flag regresses the result silently wraps to a negative int64. |
STK-REQ-007 |
determinism | medium | high | ParseFloat on the same numeric token must return the same float64 across calls; a regression in parseFloat rounding direction produces non-deterministic results across calls. |
STK-REQ-007 |
edge_case | medium | high | ParseBoolean on the empty token []byte returns (false, MalformedValueError); a regression returns (false,nil) and silently misreads empty input as boolean false. |
STK-REQ-007 |
empty_input | medium | high | ParseInt on a zero-length []byte drives parseInt to ok=false; the caller receives MalformedValueError but a regression silently returns 0 instead, masking the empty-input case. |
STK-REQ-007 |
malformed_input | medium | high | ParseFloat on a token like 1.2.3 drives parseFloat to error; a regression in the malformed check returns 1.2 (the partial parse) instead of MalformedValueError, silently corrupting numeric output. |
SYS-REQ-002 |
determinism | medium | high | GetString returns a different decoded string across calls on identical well-formed input, corrupting cache keys or byte-equality assumptions at the call site. |
SYS-REQ-009 |
idempotency | medium | high | Set on the same (input, path, value) tuple yields a different document on a second call (e.g. idempotency regression where repeated Set inserts the path twice), corrupting cache or diff layers. |
SYS-REQ-009 |
nested_mutation | medium | high | Set on a multi-segment path drives createInsertComponent to emit array scaffolding at the wrong depth or offset; a regression overwrites a sibling element or builds malformed JSON, silently corrupting the nested structure (SYS-REQ-110 hazard class). |
SYS-REQ-076 |
edge_case | medium | high | GetInt on a boundary value like -9223372036854775808 (INT64_MIN) negates it during parse and returns 0 or a wrong positive value; or on a canonical-form +0/-0 token returns wrong sign, corrupting accumulator invariants. |
SYS-REQ-110 |
nested_mutation | medium | high | Set on a beyond-length array index inside a nested container drives createInsertComponent to emit array scaffolding at the wrong offset; a regression overwrites a sibling element or builds malformed JSON, silently corrupting the nested structure. |
SYS-REQ-112 |
boundary | medium | high | An empty addressed array ([]) or object ({}) drives a regression in scanContainerLen that double-counts the closing delimiter or panics on the empty body, inverting the zero-vs-nonzero branch downstream. |
SYS-REQ-112 |
nominal | medium | high | GetArrayLen/GetObjectLen return a count that does not match the actual number of elements/pairs in the addressed container, silently corrupting downstream length-based branching. |
SYS-REQ-113 |
nominal | medium | high | EachKeyWildcard/SetWildcard emit callbacks or apply mutations in non-document order, or skip matched elements / emit extra callbacks, breaking deterministic fan-out that downstream callers rely on. |
SYS-REQ-114 |
boundary | medium | high | A root path ("$” or “$.”) or empty input drives ParsePath to return a wrong-shaped slice (nil vs empty) or to panic; the root-array-index case ("$[0]") misroutes through the dotted-key parser and returns errMalformedPath for a valid path. |
SYS-REQ-114 |
nominal | medium | high | CompiledPath methods diverge observationally from invoking the equivalent top-level function with the parsed components (different error semantics, different returned offsets, different mutated document shape), breaking the substitution invariant callers rely on. |
SYS-REQ-116 |
boundary | medium | high | A key, escape sequence, scalar, string, or composite value crossing the sliding-window boundary is truncated, duplicated, or skipped, returning corrupt value bytes or retaining the whole stream. |
SYS-REQ-116 |
empty_input | medium | high | An empty or nil reader causes a panic or an unbounded read loop instead of returning the defined not-found or malformed-input result. |
SYS-REQ-116 |
nominal | medium | high | ReaderParser returns a different value or ValueType than the byte-slice parser for the same path because incremental matching loses nesting or quote state at a read boundary. |
SYS-REQ-002 |
edge_case | low | high | GetString on a 1-char escaped body like an empty quoted string returns an out-of-range slice or wrong length, corrupting downstream string math at the caller. |
SYS-REQ-010 |
empty_input | low | high | Delete with no path returns a non-empty document instead of an empty one, leaking data the caller explicitly asked to erase. |
SYS-REQ-015 |
edge_case | low | high | ParseInt on a leading-zero canonical token like 007 returns 7 with the leading zeros stripped inconsistently, or off-by-one on a single-digit 0 token, producing wrong results for canonical-form inputs. |
SYS-REQ-015 |
malformed_input | low | high | ParseInt on a sign-only token ("-") returns (0, nil) — silent false-success — instead of MalformedValueError, masking malformed input as a valid zero (DEFECT-260726-3F95 / KI-2). |
SYS-REQ-016 |
missing_path | low | high | Get returns a stale value slice from a previously cached offset instead of KeyPathNotFoundError when the path is missing, leaking a sibling field’s bytes to the caller (silent data corruption). |
SYS-REQ-019 |
empty_input | low | high | Get on a zero-length input with a path returns a stale value slice instead of KeyPathNotFoundError, mis-classifying empty input as a found path and leaking stale bytes. |
SYS-REQ-028 |
empty_input | low | high | ArrayEach on [] emits one spurious callback with a stale element slice, misleading the caller to process a phantom element from a stale buffer. |
SYS-REQ-074 |
empty_input | low | high | GetString on an empty []byte returns an empty string without surfacing KeyPathNotFoundError, masking missing data as a valid empty string and corrupting caller presence checks. |
SYS-REQ-078 |
empty_input | low | high | GetInt on an empty []byte returns 0 (silent success) instead of KeyPathNotFoundError, masking missing data as a valid zero and corrupting accumulator invariants. |
SYS-REQ-081 |
empty_input | low | high | GetUnsafeString on an empty []byte returns a non-empty string from a stale buffer instead of the not-found result, leaking stale memory to the caller. |
SYS-REQ-001 |
determinism | medium | medium | Get on identical well-formed input returns a different (value,start,end) triple across calls; an offset-math layer downstream computes value[end-start:] past the buffer and slices out of range, panicking the caller. |
SYS-REQ-003 |
determinism | medium | medium | GetInt returns a different int64 across calls on identical well-formed input, inverting downstream branching that relies on hash/equality invariants. |
SYS-REQ-006 |
determinism | medium | medium | ArrayEach invokes callbacks in non-deterministic encounter order on identical input, breaking caller-side slice-append or sum accumulation invariants. |
SYS-REQ-011 |
determinism | medium | medium | GetUnsafeString returns different raw bytes for identical input across calls, corrupting downstream byte-equality or hash invariants. |
SYS-REQ-012 |
determinism | medium | medium | ParseBoolean returns different bools across calls on the same true/false token, inverting downstream branching logic. |
SYS-REQ-018 |
idempotency | medium | medium | Get with no path returns different root slices across calls on identical input (e.g. trims surrounding whitespace inconsistently), corrupting downstream equality or hash invariants. |
SYS-REQ-023 |
boundary | medium | medium | Get with path [5] on [1,2,3] returns the last element instead of not-found due to an off-by-one in the array bounds check, masking an out-of-range access as a valid value. |
SYS-REQ-023 |
edge_case | medium | medium | Get on a single-element array with index [0] returns wrong element due to off-by-one in i+1 increment, or panics on [1] due to unchecked post-increment dereference. |
SYS-REQ-027 |
type_mismatch | medium | medium | Get on a leading-byte token that matches no classifier (e.g. ; at value position) returns a Number or String classification anyway, mis-routing the caller into the wrong typed accessor and producing wrong downstream values. |
SYS-REQ-069 |
nested_mutation | medium | medium | Set on path [a][b] where a exists but b does not overwrites the sibling [a][c] value or builds malformed JSON like {“a”:{“b”:1}} missing a comma, silently corrupting the document. |
SYS-REQ-073 |
type_mismatch | medium | medium | GetString on a numeric value like 42 returns an empty string and silently masks the type error, corrupting the caller’s string-typed schema with phantom data. |
SYS-REQ-077 |
type_mismatch | medium | medium | GetInt on a string value like “42” silently returns 42 by accepting the wrapped token, masking the type error and corrupting the caller’s numeric schema. |
SYS-REQ-115 |
encoding_safety | medium | medium | AllowUnknownEscapes drops or duplicates bytes, consumes a malformed Unicode escape as an unknown escape, or emits a different literal value than the escaped input represents. |
SYS-REQ-115 |
malformed_input | medium | medium | DefaultConfig or an existing package-level function silently accepts single-quoted input or unknown escapes, weakening the established strict contract for callers that rely on malformed-input rejection. |
SYS-REQ-115 |
nominal | medium | medium | A Config with AllowSingleQuotes enabled fails to recognize matching single-quoted keys or values, returns incorrect offsets, or lets a quote/bracket inside a single-quoted string terminate the surrounding container early. |
SYS-REQ-008 |
edge_case | low | low | EachKeys with one requested path plus one malformed sibling emits a found-callback for the good path but loses or mis-routes the malformed-input error, leaving the caller with an incomplete scan and no error surfaced. |
SYS-REQ-034 |
edge_case | low | low | Delete on an object whose only key is the absent target rewrites the payload (e.g. drops a sibling key in cleanup), silently corrupting the document. |
SYS-REQ-034 |
missing_path | low | low | Delete on a missing nested path descends into the intermediate structure and corrupts a sibling by deleting the wrong key, producing a wrong document. |
SYS-REQ-064 |
empty_input | low | low | ParseInt on a zero-length token returns 0 (silent success) instead of MalformedValueError, masking missing data as a valid zero and corrupting downstream accumulator invariants. |
SYS-REQ-070 |
no_path_provided | low | low | Set with no path returns a byte slice or panics in findKeyStart at data[0] instead of returning KeyPathNotFoundError, mutating the wrong memory or crashing on empty input. |
One record per entity shown in this profile. Headings are the verbatim entity id, so the in-table links above resolve here.
go test -run 'TestGetEmptyKeyPathComponent|TestTypedGetEmptyKeyPathComponent|TestEachKeyEmptyKeyPathComponent|TestSetEmptyKeyPathComponent|TestDeleteEmptyKeyPathComponent' -count=1 ./...go test ./... -count=1 -race\uDC00 is substituted with U+FFFD instead of a bogus code pointCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N} else if r >= lowSurrogateOffset {) catches a lone low surrogate and returns (utf8.RuneError, 6), substituting U+FFFD and consuming exactly the six bytes of the escape — matching encoding/json and RFC 8259 handling of unpaired surrogates (relevant to CWE-20 Improper Input Validation for surrogate handling). This entry documents the already-correct, hardened behavior with a GREEN reproducer; the tripwire fires if the branch is deleted or narrowed. Intentional demo showcase entry on the proof-demo branch; never shipped.go test -run TestDemoKI15 -count=1 .go test ./... -count=1CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:Nif lk == 0 { return make([]byte, 0), true }) returns a fresh zero-length slice with a fresh backing array and found=true, so the result does not alias the caller’s input buffer. Returning the aliased input slice instead would be a CWE-1325/aliasing hazard (later writes to the returned slice could mutate the caller’s data). This entry documents the already-correct, hardened behavior with a GREEN reproducer; the tripwire fires if the guard is removed or made to alias. Intentional demo showcase entry on the proof-demo branch; never shipped.go test -run TestDemoKI16 -count=1 .go test ./... -count=1-), the remainder is empty, the loop runs zero iterations, n stays 0, and the function returns (0, true, false). The public ParseInt therefore reports a successful parse of value 0 for an input that is structurally a malformed JSON number (sign with no digits).go run -trimpath -e - <<EOF package main import ( "fmt" "github.com/buger/jsonparser" ) func main() { v, err := jsonparser.ParseInt([]byte("-")) fmt.Printf("v=%d err=%v\n", v, err) } EOFgo test -run TestParseInt ./...go test -v -run TestSetArrayIndexUnderObjectMalformedJSON_KI3 ./...go test -v -run TestSetArrayIndexUnderObjectMalformedJSON_KI3 ./...go test -v -run TestSetTopLevelArrayAppend_KI4 -count=1 ./...CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:Nbytes.Equal(b, trueLiteral) / bytes.Equal(b, falseLiteral) to bytes.HasPrefix(...) (parser.go:2137-2139), so any value that merely begins with “true” or “false” — “trueish”, “falsehood” — now parses successfully as the corresponding boolean instead of erroring. This is a CWE-20 Improper Input Validation (prefix match where exact equality is required), admitting malformed tokens as valid data. Intentional demo defect on the proof-demo showcase branch; never shipped.bytes.HasPrefix -> bytes.Equal) so only the literal “true”/“false” tokens parse and any trailing garbage returns MalformedValueError. Closes CWE-20 Improper Input Validation.go test -run TestDemoKI11 -count=1 .go test ./... -count=1CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H\u escape — one malformed byte sequence aborts the request/goroutine handling it. Intentional demo defect on the proof-demo showcase branch; never shipped in a released jsonparser.\uXXXX escape by reading four hex digits at in[2..5] after a minimum-length guard. On the proof-demo showcase branch that guard was weakened from if len(in) < 6 to if len(in) < 4 (escape.go:88), so a truncated escape such as \u00 — only four bytes available — passes the check and the decoder indexes in[4] and in[5] one and two bytes past the end of the backing slice. This is a textbook CWE-125 Out-of-bounds Read: the boundary condition (fewer than the six bytes the escape requires) is no longer rejected before the indexed reads. The Go runtime turns the out-of-bounds index into an index-out-of-range panic, so any caller parsing the input is crashed — a denial of service. Intentional demo defect on the proof-demo showcase branch; never shipped.if len(in) < 4 -> if len(in) < 6) so a truncated \uXX returns (RuneError, false) before any indexed read. Closes CWE-125 Out-of-bounds Read; cf. RFC 8259 section 7 on \uXXXX escapes.go test -run TestDemoKI5 -count=1 .go test ./... -count=1CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:Hif len(in) < 2 to if len(in) < 1 (escape.go:194), so a single-byte input \ passes the check and the escape switch reads in[1] one byte past the end of the slice — a CWE-125 Out-of-bounds Read reachable via a lone trailing backslash. The Go runtime converts the read into an index-out-of-range panic, aborting the parse. Intentional demo defect on the proof-demo showcase branch; never shipped.if len(in) < 1 -> if len(in) < 2) so a lone trailing backslash returns (-1, -1) and the caller surfaces MalformedStringEscapeError. Closes CWE-125 Out-of-bounds Read; cf. RFC 8259 section 7.go test -run TestDemoKI6 -count=1 .go test ./... -count=1CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:Nif l-i < 19 to if l-i < 20 (bytes.go:27), so a 19-digit value now takes the unchecked fast path and is accumulated with plain int64 arithmetic that wraps around on overflow instead of routing through the overflow-checked slow path. This is a CWE-190 Integer Overflow (with a downstream CWE-704 Incorrect Type Conversion): a 19-digit literal above math.MaxInt64 returns a silently wrapped, wrong int64 with a nil error rather than OverflowIntegerError. Intentional demo defect on the proof-demo showcase branch; never shipped.if l-i < 20 -> if l-i < 19) so any integer of 19-or-more digits is routed through the overflow-checked path and returns OverflowIntegerError for out-of-range input. Closes CWE-190 Integer Overflow / CWE-704 Incorrect Type Conversion.go test -run TestDemoKI7 -count=1 .go test ./... -count=1CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H\u low-surrogate continuation, guarded by a length check. On the proof-demo showcase branch the lone-high-surrogate guard was weakened from len(in) < 8 to len(in) < 6 (escape.go:146), so when only six bytes remain the short-circuit no longer protects in[6]/in[7], which are then read past the end of the slice — a CWE-125 Out-of-bounds Read. The Go runtime turns the read into an index-out-of-range panic instead of substituting U+FFFD for the unpaired surrogate. Intentional demo defect on the proof-demo showcase branch; never shipped.len(in) < 6 -> len(in) < 8) so a high surrogate at end-of-buffer substitutes U+FFFD instead of indexing past the buffer. Closes CWE-125 Out-of-bounds Read; cf. RFC 8259 section 7 on unpaired surrogates.go test -run TestDemoKI8 -count=1 .go test ./... -count=1[] is rejected as malformedCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N[], breaking otherwise-correct code paths that handle empty collections. Intentional demo defect on the proof-demo showcase branch; never shipped.if data[offset] == ']' to if data[offset] == '}' (parser.go:1763), so a valid empty array [] no longer matches the empty-array sentinel; the loop then runs against the closing bracket and returns MalformedArrayError. This is a CWE-20 Improper Input Validation: well-formed input is rejected because the sentinel compares against the wrong delimiter. Intentional demo defect on the proof-demo showcase branch; never shipped.']' closing-bracket comparison in the empty-array fast path of arrayEachConfig (parser.go:1763, data[offset] == '}' -> data[offset] == ']') so [] iterates zero times with a nil error. Closes CWE-20 Improper Input Validation.go test -run TestDemoKI10 -count=1 .go test ./... -count=1\uGxxx is silently acceptedCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:Nif c >= 65 && c <= 70 to c <= 71 (escape.go:71), so byte 71 — ASCII “G” — maps to value 16 instead of returning badHex. A \uG000 escape is then silently accepted and decoded to a bogus code point rather than being rejected. This is a CWE-20 Improper Input Validation (an off-by-one on the accepted-character bound). Intentional demo defect on the proof-demo showcase branch; never shipped.c <= 71 -> c <= 70) so any byte above “F” returns badHex and the enclosing escape is rejected as malformed. Closes CWE-20 Improper Input Validation; cf. RFC 8259 section 7.go test -run TestDemoKI9 -count=1 .go test ./... -count=1CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N|| c == '\t' term (parser.go:247), so a tab is no longer treated as insignificant whitespace and token scanning stops on it, failing to locate the following value. RFC 8259 lists the tab among the four insignificant whitespace bytes, so this is a CWE-20 Improper Input Validation — spec-valid input is rejected. Intentional demo defect on the proof-demo showcase branch; never shipped.|| c == '\t') so tab-formatted JSON parses per RFC 8259 section 2. Closes CWE-20 Improper Input Validation.go test -run TestDemoKI13 -count=1 .go test ./... -count=1\/ is rejected as malformedCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:N\/ escape (common when JSON is embedded in HTML/JS or produced by escaping-heavy encoders) fail to decode, breaking otherwise-valid documents. Intentional demo defect on the proof-demo showcase branch; never shipped./ entry (escape.go:203), so \/ falls through to the error return even though RFC 8259 explicitly permits the escaped solidus and backslashCharEscapeTable already maps it. The result is a CWE-20 Improper Input Validation: a spec-valid escape is rejected as MalformedStringEscapeError. Intentional demo defect on the proof-demo showcase branch; never shipped.'/' to the basic-escape case in unescapeToUTF8Config (escape.go:203) so \/ decodes to /. RFC 8259 section 7 permits the escaped solidus; closes CWE-20 Improper Input Validation.go test -run TestDemoKI14 -count=1 .go test ./... -count=1MalformedObjectError to MalformedJsonError (parser.go:1709), so ArrayEach on empty input surfaces an error type that disagrees with the documented contract and with the sibling arrayEachErr path. This is a CWE-20 Improper Input Validation nit — the failure is still reported, but with the wrong (inconsistent) error value. Purely informational: no security, availability, or data-integrity impact. Intentional demo defect on the proof-demo showcase branch; never shipped.MalformedJsonError -> MalformedObjectError) so the error type matches the documented contract and the arrayEachErr path. Consistency fix for CWE-20 Improper Input Validation.go test -run TestDemoKI12 -count=1 .go test ./... -count=1Title: ParseInt("-") returns (0, nil) — silent false-success on sign-only input
Severity: low
Status: covered_by_known_issue
Introduced: inception
Description: ParseInt (parser.go:1498) delegates to parseInt (bytes.go:9). When the
input is exactly a sign byte with no following digits ("-" or "+"-style
input where + is rejected because it isn’t valid JSON but - is a valid
JSON number prefix), the parser:
- (bytes.go:15-18), leaving an empty byte slice;n stays 0;if neg branch (bytes.go:43) and returns
(-0, true, false) = (0, nil).The caller (GetInt / any code using ParseInt to validate a JSON number
token) is told the input parsed successfully with value 0. This is silent
false-success on caller-controlled input: a JSON value of just - is
malformed (no digits follow the sign) but is reported as a well-formed
integer equal to zero.
Hazard class: this is the same family as the JSON fuzzer’s existing
ParseInt finding — the input partition “sign byte only, no digits” is not
covered by the parser’s malformed-input branch. The catalog obligation
malformed_input requires a typed error on this partition; the code
returns (0, nil) instead.
Set is called with a key path that contains an array-index
component [N] whose parent in the addressed JSON is an OBJECT rather
than an array, the implementation emits malformed JSON output and
returns it with a nil error. The caller has no signal that the
returned bytes cannot be re-parsed by any JSON consumer.Reproducer (filed as KI-3, locked by tripwire
set_spec_test.go:TestSetArrayIndexUnderObjectMalformedJSON_KI3):
Set({"a":{"b":1}}, 9, “a”, “[5]”) -> {"a":{"b":1,9}} (INVALID)
Set({"a":{"b":1}}, 9, “a”, “[0]”, “x”) -> {"a":{"b":1,{"x":9}}} (INVALID)
Set({"a":1}, 9, “[0]”) -> {"a":1,9} (INVALID)
Each output is rejected by encoding/json.Unmarshal with “invalid
character ‘9’ looking for beginning of object key string” or similar.
Root cause: createInsertComponent (parser.go:756) with
isIndex=true, comma=true, object=false emits only ,<value> (no
quoted object key), so the value is spliced into the object body where
JSON requires a "key":value pair. Set (parser.go:1018-1038) does
not reject the cross-type path before invoking
createInsertComponent. The symmetric case (object-key component under
an array parent) is handled by auto-vivification, so the bug is
specifically [N]-under-object.
Hazard class: this is the same family as PR #286 (silent data
corruption on underspecified Set partitions). The partition “path
component kind mismatches its parent container kind” was not covered
by SYS-REQ-009’s fretish. The catalog obligation malformed_input is
now attached to SYS-REQ-009 so the audit enforces this failure mode
henceforth.
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.
[] 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.[ as an array element; for object/number input, this misinterpreted
the first content byte as an element and invoked the callback with
bogus data before the structural-malformed check triggered.data[subObjOff] == '{',
limiting the append path to arrays whose first element is an object.
All other non-empty arrays fell through to the “replace container”
branch (object=true), destroying existing elements.Title: Delete left dangling trailing comma on array/object element followed by whitespace+comma
Severity: high
Status: covered_by_requirement
Introduced: inception
Fixing / upstream ref: hazard-sweep: FuzzPathMutation crashers ed0b39400500dd8f / 798e17d6cde9ba4b / 7095d73632e4979e / 19be37bd98e5d687
Description: Delete (parser.go:864) produced malformed JSON output (rejected by
encoding/json.Unmarshal) whenever the deleted element was followed by
one or more JSON whitespace bytes (space, tab, LF, CR) and then a comma
or the container close bracket. The dangling-byte sequences were:
Delete("[0,0 ]", "[1]") -> [0, ] (trailing comma before ])Delete("[0,0 ,0]", "[1]") -> [0, ,0] (dangling comma between spaces)Delete("[0,0\n,0]", "[1]") -> [0,\n,0] (newline variant)Delete("[0,0 ,0]", "[1]") -> [0, ,0] (multi-space variant)Root cause was two-fold:
The array-branch cleanup (parser.go:932-938, data[idx] == ']' case)
only advanced keyOffset to tokStart; it did not handle the
whitespace-before-] shape, so the cleanup block ran with the wrong
endOffset and left the comma.
The array-branch whitespace-then-comma case was missing entirely.
The object-branch (parser.go:907-916) had data[idx] == ' ' && data[nextIdx] == ',', but (a) it only matched a SINGLE 0x20 space,
missing \t, \n, \r, and multi-byte whitespace runs, and (b) the
symmetric case was absent from the array branch.
The final cleanup (parser.go:948) only checked remainedValue[i] == '}' (object close), so deleting the LAST array element left the
comma dangling before ].
Hazard class: silent malformed-JSON output on caller-controlled input shape (whitespace placement is arbitrary in JSON). Found by FuzzPathMutation during the final hazard sweep.
e1408e32ad385bf0escape_test.go:TestUnescapeLoneHighSurrogateescape_test.go:TestUnescapeLoneHighSurrogateFollowedByNonEscapeescape_test.go:TestUnescapeLoneLowSurrogateescape_test.go:TestUnescapeHighSurrogateThenNonSurrogateescape_test.go:TestUnescapeValidSurrogatePairStillWorksescape_test.go:TestParseStringLoneSurrogateMatchesEncodingJSONFields this report had to infer or reconstruct because the model does not carry them as first-class data. Occurrences = records hitting the gap in this run.
| Field | Severity | Occurrences | Came from | Proposed model addition |
|---|---|---|---|---|
KnownIssue.resolved_at |
lossy | 6 | inferred from history[].at of the entry whose detail matches a status->fixed transition | add resolved_at string (RFC3339), set by proof known-issue resolve |
KnownIssue.resolved_in |
blocking | 6 | reconstructed from non-model fixing_reference: key, else scavenged #PR/SHA from history detail or remediation prose |
add resolved_in string (fixing commit-ish); promote the de-facto fixing_reference YAML key into the model so it stops being dropped on load |
KnownIssue.created_at |
lossy | 0 | inferred from the first history[] entry (action=created) | add created_at string; age/SLA math currently depends on a history convention |
ProblemReport.detected_at |
lossy | 0 | source.date, else regression.detected_at (when a date), else first history entry | add a report-level detected_at; regression.detected_at is overloaded (sometimes a SHA, not a date) |
ProblemReport.regression.dwell |
cosmetic | 0 | read directly when present; frequently empty — not derivable without bisect | auto-derive dwell from introduced_in..fixed_in via git, or require it on regression closure |