Proof Portal

Projects

jsonparser

ProbeLabs36 findings · 123 requirements
Back to findings
Known issueKI-15

decodeUnicodeEscape lone low surrogate `\uDC00` is substituted with U+FFFD instead of a bogus code point

FixedFixedMedium

This defect has been fixed and verified.

Introduced

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

Inception (latent from the first version)

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.

Reachability

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).

MediumRated severity — the impact if this issue is exploited or hit.
why this rating
Risk-rated
risk area
Correctness
Security classification
Security-relevant
CVSS
CVSS 5.3· Mediumv3.1CVSS: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.

Known issue reproducedprovesSYS-REQ-062
Run it yourself
go test -run TestDemoKI15 -count=1 .
Covers (3)
Last run Aug 3, 2026, 11:00 AM

Reproduction steps

Technical steps for your engineers to confirm the issue by hand.

  1. Check out the proof-demo showcase branch and build the package.
  2. Call jsonparser.GetString on a value containing `\uDC00` — or run: go test -run TestDemoKI15 -count=1 .
  3. 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.)

Tracing blast radius…

Per-requirement evidence

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

Tests & evidence (3)
  • README.md
  • deep_spec_test.go
  • mcdc_spec_witnesses_test.go

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.

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