From 2a22aefa1f7befb0ac7a95c918b75b05919c1907 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Thu, 26 Jun 2025 12:19:23 -0700 Subject: [PATCH] encoding/json: add security section to doc Add a section to the package doc which details the security considerations of using encoding/json, in particular with respect to parser misalignment issues. Additionally, clarify previously ambiguous statement in the Unmarshal doc about how case is used when matching keys in objects, and add a note about how duplicate keys are handled. Fixes #14750 Change-Id: I66f9b845efd98c86a684d7333b3aa8a456564922 Reviewed-on: https://go-review.googlesource.com/c/go/+/684315 LUCI-TryBot-Result: Go LUCI Reviewed-by: Joseph Tsai Auto-Submit: Roland Shoemaker Reviewed-by: Damien Neil --- src/encoding/json/decode.go | 13 ++++++++----- src/encoding/json/encode.go | 38 ++++++++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/encoding/json/decode.go b/src/encoding/json/decode.go index 4e195e0948..70885a517e 100644 --- a/src/encoding/json/decode.go +++ b/src/encoding/json/decode.go @@ -43,11 +43,14 @@ import ( // and the input is a JSON quoted string, Unmarshal calls // [encoding.TextUnmarshaler.UnmarshalText] with the unquoted form of the string. // -// To unmarshal JSON into a struct, Unmarshal matches incoming object -// keys to the keys used by [Marshal] (either the struct field name or its tag), -// preferring an exact match but also accepting a case-insensitive match. By -// default, object keys which don't have a corresponding struct field are -// ignored (see [Decoder.DisallowUnknownFields] for an alternative). +// To unmarshal JSON into a struct, Unmarshal matches incoming object keys to +// the keys used by [Marshal] (either the struct field name or its tag), +// ignoring case. If multiple struct fields match an object key, an exact case +// match is preferred over a case-insensitive one. +// +// Incoming object members are processed in the order observed. If an object +// includes duplicate keys, later duplicates will replace or be merged into +// prior values. // // To unmarshal JSON into an interface value, // Unmarshal stores one of these in the interface value: diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go index 1992e7372e..29fcc91fd7 100644 --- a/src/encoding/json/encode.go +++ b/src/encoding/json/encode.go @@ -4,12 +4,44 @@ //go:build !goexperiment.jsonv2 -// Package json implements encoding and decoding of JSON as defined in -// RFC 7159. The mapping between JSON and Go values is described -// in the documentation for the Marshal and Unmarshal functions. +// Package json implements encoding and decoding of JSON as defined in RFC 7159. +// The mapping between JSON and Go values is described in the documentation for +// the Marshal and Unmarshal functions. // // See "JSON and Go" for an introduction to this package: // https://golang.org/doc/articles/json_and_go.html +// +// # Security Considerations +// +// The JSON standard (RFC 7159) is lax in its definition of a number of parser +// behaviors. As such, many JSON parsers behave differently in various +// scenarios. These differences in parsers mean that systems that use multiple +// independent JSON parser implementations may parse the same JSON object in +// differing ways. +// +// Systems that rely on a JSON object being parsed consistently for security +// purposes should be careful to understand the behaviors of this parser, as +// well as how these behaviors may cause interoperability issues with other +// parser implementations. +// +// Due to the Go Backwards Compatibility promise (https://go.dev/doc/go1compat) +// there are a number of behaviors this package exhibits that may cause +// interopability issues, but cannot be changed. In particular the following +// parsing behaviors may cause issues: +// +// - If a JSON object contains duplicate keys, keys are processed in the order +// they are observed, meaning later values will replace or be merged into +// prior values, depending on the field type (in particular maps and structs +// will have values merged, while other types have values replaced). +// - When parsing a JSON object into a Go struct, keys are considered in a +// case-insensitive fashion. +// - When parsing a JSON object into a Go struct, unknown keys in the JSON +// object are ignored (unless a [Decoder] is used and +// [Decoder.DisallowUnknownFields] has been called). +// - Invalid UTF-8 bytes in JSON strings are replaced by the Unicode +// replacement character. +// - Large JSON number integers will lose precision when unmarshaled into +// floating-point types. package json import ( -- 2.50.0