]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/json/v2: add security section to doc
authorJoe Tsai <joetsai@digital-static.net>
Tue, 1 Jul 2025 05:17:41 +0000 (22:17 -0700)
committerGopher Robot <gobot@golang.org>
Mon, 14 Jul 2025 14:58:11 +0000 (07:58 -0700)
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 <joetsai@digital-static.net>
Reviewed-by: Damien Neil <dneil@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
src/encoding/json/jsontext/doc.go
src/encoding/json/jsontext/options.go
src/encoding/json/v2/doc.go
src/encoding/json/v2_encode.go

index 8e4bced015d0000077402de9034b4925d14a910f..d8906926863a86de7b1a7d4944bfea4f605e0491 100644 (file)
 // RFC 7493 is a stricter subset of RFC 8259 and fully compliant with it.
 // In particular, it makes specific choices about behavior that RFC 8259
 // leaves as undefined in order to ensure greater interoperability.
+//
+// # Security Considerations
+//
+// See the "Security Considerations" section in [encoding/json/v2].
 package jsontext
 
 // requireKeyedLiterals can be embedded in a struct to require keyed literals.
index e07de21fcfdd6015e78f35785cdbd819b6b01c42..7eb4f9b9e048a830e9022e142ac7a88a67447710 100644 (file)
@@ -271,6 +271,7 @@ func WithIndentPrefix(prefix string) Options {
 
 /*
 // TODO(https://go.dev/issue/56733): Implement WithByteLimit and WithDepthLimit.
+// Remember to also update the "Security Considerations" section.
 
 // WithByteLimit sets a limit on the number of bytes of input or output bytes
 // that may be consumed or produced for each top-level JSON value.
index 203139754c203449fde420f9886b0110ffdf9e38..8179f8ab179504d44d3900262b178519d600f6eb 100644 (file)
 // Marshaling or unmarshaling a non-empty struct
 // without any JSON representable fields results in a [SemanticError].
 // Unexported fields must not have any `json` tags except for `json:"-"`.
+//
+// # Security Considerations
+//
+// JSON is frequently used as a data interchange format to communicate
+// between different systems, possibly implemented in different languages.
+// For interoperability and security reasons, it is important that
+// all implementations agree upon the semantic meaning of the data.
+//
+// [For example, suppose we have two micro-services.]
+// The first service is responsible for authenticating a JSON request,
+// while the second service is responsible for executing the request
+// (having assumed that the prior service authenticated the request).
+// If an attacker were able to maliciously craft a JSON request such that
+// both services believe that the same request is from different users,
+// it could bypass the authenticator with valid credentials for one user,
+// but maliciously perform an action on behalf of a different user.
+//
+// According to RFC 8259, there unfortunately exist many JSON texts
+// that are syntactically valid but semantically ambiguous.
+// For example, the standard does not define how to interpret duplicate
+// names within an object.
+//
+// The v1 [encoding/json] and [encoding/json/v2] packages
+// interpret some inputs in different ways. In particular:
+//
+//   - The standard specifies that JSON must be encoded using UTF-8.
+//     By default, v1 replaces invalid bytes of UTF-8 in JSON strings
+//     with the Unicode replacement character,
+//     while v2 rejects inputs with invalid UTF-8.
+//     To change the default, specify the [jsontext.AllowInvalidUTF8] option.
+//     The replacement of invalid UTF-8 is a form of data corruption
+//     that alters the precise meaning of strings.
+//
+//   - The standard does not specify a particular behavior when
+//     duplicate names are encountered within a JSON object,
+//     which means that different implementations may behave differently.
+//     By default, v1 allows for the presence of duplicate names,
+//     while v2 rejects duplicate names.
+//     To change the default, specify the [jsontext.AllowDuplicateNames] option.
+//     If allowed, object members are processed in the order they are observed,
+//     meaning that later values will replace or be merged into prior values,
+//     depending on the Go value type.
+//
+//   - The standard defines a JSON object as an unordered collection of name/value pairs.
+//     While ordering can be observed through the underlying [jsontext] API,
+//     both v1 and v2 generally avoid exposing the ordering.
+//     No application should semantically depend on the order of object members.
+//     Allowing duplicate names is a vector through which ordering of members
+//     can accidentally be observed and depended upon.
+//
+//   - The standard suggests that JSON object names are typically compared
+//     based on equality of the sequence of Unicode code points,
+//     which implies that comparing names is often case-sensitive.
+//     When unmarshaling a JSON object into a Go struct,
+//     by default, v1 uses a (loose) case-insensitive match on the name,
+//     while v2 uses a (strict) case-sensitive match on the name.
+//     To change the default, specify the [MatchCaseInsensitiveNames] option.
+//     The use of case-insensitive matching provides another vector through
+//     which duplicate names can occur. Allowing case-insensitive matching
+//     means that v1 or v2 might interpret JSON objects differently from most
+//     other JSON implementations (which typically use a case-sensitive match).
+//
+//   - The standard does not specify a particular behavior when
+//     an unknown name in a JSON object is encountered.
+//     When unmarshaling a JSON object into a Go struct, by default
+//     both v1 and v2 ignore unknown names and their corresponding values.
+//     To change the default, specify the [RejectUnknownMembers] option.
+//
+//   - The standard suggests that implementations may use a float64
+//     to represent a JSON number. Consequently, large JSON integers
+//     may lose precision when stored as a floating-point type.
+//     Both v1 and v2 correctly preserve precision when marshaling and
+//     unmarshaling a concrete integer type. However, even if v1 and v2
+//     preserve precision for concrete types, other JSON implementations
+//     may not be able to preserve precision for outputs produced by v1 or v2.
+//     The `string` tag option can be used to specify that an integer type
+//     is to be quoted within a JSON string to avoid loss of precision.
+//     Furthermore, v1 and v2 may still lose precision when unmarshaling
+//     into an any interface value, where unmarshal uses a float64
+//     by default to represent a JSON number.
+//     To change the default, specify the [WithUnmarshalers] option
+//     with a custom unmarshaler that pre-populates the interface value
+//     with a concrete Go type that can preserve precision.
+//
+// RFC 8785 specifies a canonical form for any JSON text,
+// which explicitly defines specific behaviors that RFC 8259 leaves undefined.
+// In theory, if a text can successfully [jsontext.Value.Canonicalize]
+// without changing the semantic meaning of the data, then it provides a
+// greater degree of confidence that the data is more secure and interoperable.
+//
+// The v2 API generally chooses more secure defaults than v1,
+// but care should still be taken with large integers or unknown members.
+//
+// [For example, suppose we have two micro-services.]: https://www.youtube.com/watch?v=avilmOcHKHE&t=1057s
 package json
 
 // requireKeyedLiterals can be embedded in a struct to require keyed literals.
index cbb167dbd0df4091e3979ec0c46a6e04b9810109..c2d620bcbb2d3230650f7397eec9badbdf48fa1b 100644 (file)
 //
 // See "JSON and Go" for an introduction to this package:
 // https://golang.org/doc/articles/json_and_go.html
+//
+// # Security Considerations
+//
+// See the "Security Considerations" section in [encoding/json/v2].
+//
+// For historical reasons, the default behavior of v1 [encoding/json]
+// unfortunately operates with less secure defaults.
+// New usages of JSON in Go are encouraged to use [encoding/json/v2] instead.
 package json
 
 import (