Proof Portal
jsonparser
ProbeLabs36 findings · 123 requirementsdecodeUnicodeEscape lone low surrogate `\uDC00` is substituted with U+FFFD instead of a bogus code point
This defect has been fixed and verified.
Introduced
When and where this issue first entered the codebase — the commit it traces back to.
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.
Lone low-surrogate escapes decode to the U+FFFD replacement character exactly as encoding/json does, so consumers get spec-conformant, predictable output for unpaired surrogates. This entry documents already-correct behavior with a green reproducer on the proof-demo showcase branch; never shipped.
Reachable via any Unescape/ParseString/Get* call decoding a lone low-surrogate escape; the guard now handles it, so the reproducer is green.
Technical description
decodeUnicodeEscape (escape.go) must reject an unpaired low surrogate rather than fold it into a surrogate-pair calculation. The guard at escape.go:138 (`} 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.
Severity, explained
Why this is rated the way it is — and the scoring signals behind the rating (each ⓘ explains the term).
- why this rating
- Risk-rated
- risk area
- Correctness
- CVSS
- CVSS 5.3· Mediumv3.1
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N - CVE surface
- None
Where it is
The code the issue lives in — peek the affected function inline to see it in context.
- decodeUnicodeEscape
How it's proven
The reproducer — an actual test that drives the real code and shows the issue happening. Run it yourself, or peek the test and the source it covers.
go test -run TestDemoKI15 -count=1 .
Reproduction steps
Technical steps for your engineers to confirm the issue by hand.
- Check out the proof-demo showcase branch and build the package.
- Call jsonparser.GetString on a value containing `\uDC00` — or run: go test -run TestDemoKI15 -count=1 .
- Observe the escape decode to U+FFFD (replacement character) with exactly 6 bytes consumed; the reproducer is green.
go test -run TestDemoKI15 -count=1 . go test ./... -count=1
How it can be triggered
The input or condition that sets this issue off.
a JSON string containing a lone low surrogate escape (0xDC00-0xDFFF), e.g. {"k":"\uDC00"}
What protects you, and the fix
What limits your exposure today, and the planned remediation.
What protects you now
No action needed for users — the lone-low-surrogate branch already substitutes U+FFFD and consumes the full 6-byte escape.
The fix
No further action required: the lone-low-surrogate guard (escape.go:138) is present and correct, matching encoding/json. This KI documents the resolved behavior; cf. RFC 8259 section 7 and CWE-20 Improper Input Validation for surrogate handling.
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.
These requirements have no implementing code to trace into — that absence is itself the risk. The graph shows the finding and the requirements it affects, but there is no code path to follow. (Tests may exist; without implementing code there is still nothing to trace into.)
Per-requirement evidence
For each requirement this finding touches: the implementing code, verifying tests, and proof obligations that discharge it.
Per-requirement evidence
For each requirement this finding touches: the implementing code, verifying tests, and proof obligations that discharge it.
Evidence trail
The raw evidence manifests behind this finding — superseded by the resolved reproducer above, kept here for traceability.
Evidence trail
The raw evidence manifests behind this finding — superseded by the resolved reproducer above, kept here for traceability.
- proof/evidence/KI-15-reproducer.yaml
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.