Skip to content

Commit c6556b8

Browse files
dsnetgopherbot
authored andcommitted
encoding/json/v2: add security section to doc
This follows up CL 684315 with an expanded section in the v2 doc. Updates #14750 Updates #71845 Change-Id: I1ffa97e030f5f2b709e8142028e3c8e0e38b80ce Reviewed-on: https://go-review.googlesource.com/c/go/+/685195 Auto-Submit: Joseph Tsai <[email protected]> Reviewed-by: Damien Neil <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Cherry Mui <[email protected]>
1 parent 6ebb5f5 commit c6556b8

File tree

4 files changed

+107
-0
lines changed

4 files changed

+107
-0
lines changed

src/encoding/json/jsontext/doc.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@
103103
// RFC 7493 is a stricter subset of RFC 8259 and fully compliant with it.
104104
// In particular, it makes specific choices about behavior that RFC 8259
105105
// leaves as undefined in order to ensure greater interoperability.
106+
//
107+
// # Security Considerations
108+
//
109+
// See the "Security Considerations" section in [encoding/json/v2].
106110
package jsontext
107111

108112
// requireKeyedLiterals can be embedded in a struct to require keyed literals.

src/encoding/json/jsontext/options.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ func WithIndentPrefix(prefix string) Options {
271271

272272
/*
273273
// TODO(https://go.dev/issue/56733): Implement WithByteLimit and WithDepthLimit.
274+
// Remember to also update the "Security Considerations" section.
274275
275276
// WithByteLimit sets a limit on the number of bytes of input or output bytes
276277
// that may be consumed or produced for each top-level JSON value.

src/encoding/json/v2/doc.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,100 @@
166166
// Marshaling or unmarshaling a non-empty struct
167167
// without any JSON representable fields results in a [SemanticError].
168168
// Unexported fields must not have any `json` tags except for `json:"-"`.
169+
//
170+
// # Security Considerations
171+
//
172+
// JSON is frequently used as a data interchange format to communicate
173+
// between different systems, possibly implemented in different languages.
174+
// For interoperability and security reasons, it is important that
175+
// all implementations agree upon the semantic meaning of the data.
176+
//
177+
// [For example, suppose we have two micro-services.]
178+
// The first service is responsible for authenticating a JSON request,
179+
// while the second service is responsible for executing the request
180+
// (having assumed that the prior service authenticated the request).
181+
// If an attacker were able to maliciously craft a JSON request such that
182+
// both services believe that the same request is from different users,
183+
// it could bypass the authenticator with valid credentials for one user,
184+
// but maliciously perform an action on behalf of a different user.
185+
//
186+
// According to RFC 8259, there unfortunately exist many JSON texts
187+
// that are syntactically valid but semantically ambiguous.
188+
// For example, the standard does not define how to interpret duplicate
189+
// names within an object.
190+
//
191+
// The v1 [encoding/json] and [encoding/json/v2] packages
192+
// interpret some inputs in different ways. In particular:
193+
//
194+
// - The standard specifies that JSON must be encoded using UTF-8.
195+
// By default, v1 replaces invalid bytes of UTF-8 in JSON strings
196+
// with the Unicode replacement character,
197+
// while v2 rejects inputs with invalid UTF-8.
198+
// To change the default, specify the [jsontext.AllowInvalidUTF8] option.
199+
// The replacement of invalid UTF-8 is a form of data corruption
200+
// that alters the precise meaning of strings.
201+
//
202+
// - The standard does not specify a particular behavior when
203+
// duplicate names are encountered within a JSON object,
204+
// which means that different implementations may behave differently.
205+
// By default, v1 allows for the presence of duplicate names,
206+
// while v2 rejects duplicate names.
207+
// To change the default, specify the [jsontext.AllowDuplicateNames] option.
208+
// If allowed, object members are processed in the order they are observed,
209+
// meaning that later values will replace or be merged into prior values,
210+
// depending on the Go value type.
211+
//
212+
// - The standard defines a JSON object as an unordered collection of name/value pairs.
213+
// While ordering can be observed through the underlying [jsontext] API,
214+
// both v1 and v2 generally avoid exposing the ordering.
215+
// No application should semantically depend on the order of object members.
216+
// Allowing duplicate names is a vector through which ordering of members
217+
// can accidentally be observed and depended upon.
218+
//
219+
// - The standard suggests that JSON object names are typically compared
220+
// based on equality of the sequence of Unicode code points,
221+
// which implies that comparing names is often case-sensitive.
222+
// When unmarshaling a JSON object into a Go struct,
223+
// by default, v1 uses a (loose) case-insensitive match on the name,
224+
// while v2 uses a (strict) case-sensitive match on the name.
225+
// To change the default, specify the [MatchCaseInsensitiveNames] option.
226+
// The use of case-insensitive matching provides another vector through
227+
// which duplicate names can occur. Allowing case-insensitive matching
228+
// means that v1 or v2 might interpret JSON objects differently from most
229+
// other JSON implementations (which typically use a case-sensitive match).
230+
//
231+
// - The standard does not specify a particular behavior when
232+
// an unknown name in a JSON object is encountered.
233+
// When unmarshaling a JSON object into a Go struct, by default
234+
// both v1 and v2 ignore unknown names and their corresponding values.
235+
// To change the default, specify the [RejectUnknownMembers] option.
236+
//
237+
// - The standard suggests that implementations may use a float64
238+
// to represent a JSON number. Consequently, large JSON integers
239+
// may lose precision when stored as a floating-point type.
240+
// Both v1 and v2 correctly preserve precision when marshaling and
241+
// unmarshaling a concrete integer type. However, even if v1 and v2
242+
// preserve precision for concrete types, other JSON implementations
243+
// may not be able to preserve precision for outputs produced by v1 or v2.
244+
// The `string` tag option can be used to specify that an integer type
245+
// is to be quoted within a JSON string to avoid loss of precision.
246+
// Furthermore, v1 and v2 may still lose precision when unmarshaling
247+
// into an any interface value, where unmarshal uses a float64
248+
// by default to represent a JSON number.
249+
// To change the default, specify the [WithUnmarshalers] option
250+
// with a custom unmarshaler that pre-populates the interface value
251+
// with a concrete Go type that can preserve precision.
252+
//
253+
// RFC 8785 specifies a canonical form for any JSON text,
254+
// which explicitly defines specific behaviors that RFC 8259 leaves undefined.
255+
// In theory, if a text can successfully [jsontext.Value.Canonicalize]
256+
// without changing the semantic meaning of the data, then it provides a
257+
// greater degree of confidence that the data is more secure and interoperable.
258+
//
259+
// The v2 API generally chooses more secure defaults than v1,
260+
// but care should still be taken with large integers or unknown members.
261+
//
262+
// [For example, suppose we have two micro-services.]: https://www.youtube.com/watch?v=avilmOcHKHE&t=1057s
169263
package json
170264

171265
// requireKeyedLiterals can be embedded in a struct to require keyed literals.

src/encoding/json/v2_encode.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010
//
1111
// See "JSON and Go" for an introduction to this package:
1212
// https://golang.org/doc/articles/json_and_go.html
13+
//
14+
// # Security Considerations
15+
//
16+
// See the "Security Considerations" section in [encoding/json/v2].
17+
//
18+
// For historical reasons, the default behavior of v1 [encoding/json]
19+
// unfortunately operates with less secure defaults.
20+
// New usages of JSON in Go are encouraged to use [encoding/json/v2] instead.
1321
package json
1422

1523
import (

0 commit comments

Comments
 (0)