summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_6.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/go/go-1.14/CVE-2023-24538_6.patch')
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-24538_6.patch371
1 files changed, 371 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_6.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_6.patch
new file mode 100644
index 0000000000..baf400b891
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-24538_6.patch
@@ -0,0 +1,371 @@
1From 16f4882984569f179d73967c9eee679bb9b098c5 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Mon, 20 Mar 2023 11:01:13 -0700
4Subject: [PATCH 6/6] html/template: disallow actions in JS template literals
5
6ECMAScript 6 introduced template literals[0][1] which are delimited with
7backticks. These need to be escaped in a similar fashion to the
8delimiters for other string literals. Additionally template literals can
9contain special syntax for string interpolation.
10
11There is no clear way to allow safe insertion of actions within JS
12template literals, as handling (JS) string interpolation inside of these
13literals is rather complex. As such we've chosen to simply disallow
14template actions within these template literals.
15
16A new error code is added for this parsing failure case, errJsTmplLit,
17but it is unexported as it is not backwards compatible with other minor
18release versions to introduce an API change in a minor release. We will
19export this code in the next major release.
20
21The previous behavior (with the cavet that backticks are now escaped
22properly) can be re-enabled with GODEBUG=jstmpllitinterp=1.
23
24This change subsumes CL471455.
25
26Thanks to Sohom Datta, Manipal Institute of Technology, for reporting
27this issue.
28
29Fixes CVE-2023-24538
30For #59234
31Fixes #59271
32
33[0] https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-template-literals
34[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
35
36Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802457
37Reviewed-by: Damien Neil <dneil@google.com>
38Run-TryBot: Damien Neil <dneil@google.com>
39Reviewed-by: Julie Qiu <julieqiu@google.com>
40Reviewed-by: Roland Shoemaker <bracewell@google.com>
41Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1802612
42Run-TryBot: Roland Shoemaker <bracewell@google.com>
43Change-Id: Ic7f10595615f2b2740d9c85ad7ef40dc0e78c04c
44Reviewed-on: https://go-review.googlesource.com/c/go/+/481987
45Auto-Submit: Michael Knyszek <mknyszek@google.com>
46TryBot-Result: Gopher Robot <gobot@golang.org>
47Run-TryBot: Michael Knyszek <mknyszek@google.com>
48Reviewed-by: Matthew Dempsky <mdempsky@google.com>
49
50Upstream-Status: Backport from https://github.com/golang/go/commit/b1e3ecfa06b67014429a197ec5e134ce4303ad9b
51CVE: CVE-2023-24538
52Signed-off-by: Shubham Kulkarni <skulkarni@mvista.com>
53---
54 src/html/template/context.go | 2 ++
55 src/html/template/error.go | 13 ++++++++
56 src/html/template/escape.go | 11 +++++++
57 src/html/template/escape_test.go | 66 ++++++++++++++++++++++-----------------
58 src/html/template/js.go | 2 ++
59 src/html/template/js_test.go | 2 +-
60 src/html/template/jsctx_string.go | 9 ++++++
61 src/html/template/state_string.go | 37 ++++++++++++++++++++--
62 src/html/template/transition.go | 7 ++++-
63 9 files changed, 116 insertions(+), 33 deletions(-)
64
65diff --git a/src/html/template/context.go b/src/html/template/context.go
66index f7d4849..0b65313 100644
67--- a/src/html/template/context.go
68+++ b/src/html/template/context.go
69@@ -116,6 +116,8 @@ const (
70 stateJSDqStr
71 // stateJSSqStr occurs inside a JavaScript single quoted string.
72 stateJSSqStr
73+ // stateJSBqStr occurs inside a JavaScript back quoted string.
74+ stateJSBqStr
75 // stateJSRegexp occurs inside a JavaScript regexp literal.
76 stateJSRegexp
77 // stateJSBlockCmt occurs inside a JavaScript /* block comment */.
78diff --git a/src/html/template/error.go b/src/html/template/error.go
79index 0e52706..fd26b64 100644
80--- a/src/html/template/error.go
81+++ b/src/html/template/error.go
82@@ -211,6 +211,19 @@ const (
83 // pipeline occurs in an unquoted attribute value context, "html" is
84 // disallowed. Avoid using "html" and "urlquery" entirely in new templates.
85 ErrPredefinedEscaper
86+
87+ // errJSTmplLit: "... appears in a JS template literal"
88+ // Example:
89+ // <script>var tmpl = `{{.Interp}`</script>
90+ // Discussion:
91+ // Package html/template does not support actions inside of JS template
92+ // literals.
93+ //
94+ // TODO(rolandshoemaker): we cannot add this as an exported error in a minor
95+ // release, since it is backwards incompatible with the other minor
96+ // releases. As such we need to leave it unexported, and then we'll add it
97+ // in the next major release.
98+ errJSTmplLit
99 )
100
101 func (e *Error) Error() string {
102diff --git a/src/html/template/escape.go b/src/html/template/escape.go
103index f12dafa..29ca5b3 100644
104--- a/src/html/template/escape.go
105+++ b/src/html/template/escape.go
106@@ -8,6 +8,7 @@ import (
107 "bytes"
108 "fmt"
109 "html"
110+ "internal/godebug"
111 "io"
112 "text/template"
113 "text/template/parse"
114@@ -203,6 +204,16 @@ func (e *escaper) escapeAction(c context, n *parse.ActionNode) context {
115 c.jsCtx = jsCtxDivOp
116 case stateJSDqStr, stateJSSqStr:
117 s = append(s, "_html_template_jsstrescaper")
118+ case stateJSBqStr:
119+ debugAllowActionJSTmpl := godebug.Get("jstmpllitinterp")
120+ if debugAllowActionJSTmpl == "1" {
121+ s = append(s, "_html_template_jsstrescaper")
122+ } else {
123+ return context{
124+ state: stateError,
125+ err: errorf(errJSTmplLit, n, n.Line, "%s appears in a JS template literal", n),
126+ }
127+ }
128 case stateJSRegexp:
129 s = append(s, "_html_template_jsregexpescaper")
130 case stateCSS:
131diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
132index fa2b84a..1b150e9 100644
133--- a/src/html/template/escape_test.go
134+++ b/src/html/template/escape_test.go
135@@ -681,35 +681,31 @@ func TestEscape(t *testing.T) {
136 }
137
138 for _, test := range tests {
139- tmpl := New(test.name)
140- tmpl = Must(tmpl.Parse(test.input))
141- // Check for bug 6459: Tree field was not set in Parse.
142- if tmpl.Tree != tmpl.text.Tree {
143- t.Errorf("%s: tree not set properly", test.name)
144- continue
145- }
146- b := new(bytes.Buffer)
147- if err := tmpl.Execute(b, data); err != nil {
148- t.Errorf("%s: template execution failed: %s", test.name, err)
149- continue
150- }
151- if w, g := test.output, b.String(); w != g {
152- t.Errorf("%s: escaped output: want\n\t%q\ngot\n\t%q", test.name, w, g)
153- continue
154- }
155- b.Reset()
156- if err := tmpl.Execute(b, pdata); err != nil {
157- t.Errorf("%s: template execution failed for pointer: %s", test.name, err)
158- continue
159- }
160- if w, g := test.output, b.String(); w != g {
161- t.Errorf("%s: escaped output for pointer: want\n\t%q\ngot\n\t%q", test.name, w, g)
162- continue
163- }
164- if tmpl.Tree != tmpl.text.Tree {
165- t.Errorf("%s: tree mismatch", test.name)
166- continue
167- }
168+ t.Run(test.name, func(t *testing.T) {
169+ tmpl := New(test.name)
170+ tmpl = Must(tmpl.Parse(test.input))
171+ // Check for bug 6459: Tree field was not set in Parse.
172+ if tmpl.Tree != tmpl.text.Tree {
173+ t.Fatalf("%s: tree not set properly", test.name)
174+ }
175+ b := new(strings.Builder)
176+ if err := tmpl.Execute(b, data); err != nil {
177+ t.Fatalf("%s: template execution failed: %s", test.name, err)
178+ }
179+ if w, g := test.output, b.String(); w != g {
180+ t.Fatalf("%s: escaped output: want\n\t%q\ngot\n\t%q", test.name, w, g)
181+ }
182+ b.Reset()
183+ if err := tmpl.Execute(b, pdata); err != nil {
184+ t.Fatalf("%s: template execution failed for pointer: %s", test.name, err)
185+ }
186+ if w, g := test.output, b.String(); w != g {
187+ t.Fatalf("%s: escaped output for pointer: want\n\t%q\ngot\n\t%q", test.name, w, g)
188+ }
189+ if tmpl.Tree != tmpl.text.Tree {
190+ t.Fatalf("%s: tree mismatch", test.name)
191+ }
192+ })
193 }
194 }
195
196@@ -936,6 +932,10 @@ func TestErrors(t *testing.T) {
197 "{{range .Items}}<a{{if .X}}{{end}}>{{if .X}}{{break}}{{end}}{{end}}",
198 "",
199 },
200+ {
201+ "<script>var a = `${a+b}`</script>`",
202+ "",
203+ },
204 // Error cases.
205 {
206 "{{if .Cond}}<a{{end}}",
207@@ -1082,6 +1082,10 @@ func TestErrors(t *testing.T) {
208 // html is allowed since it is the last command in the pipeline, but urlquery is not.
209 `predefined escaper "urlquery" disallowed in template`,
210 },
211+ {
212+ "<script>var tmpl = `asd {{.}}`;</script>",
213+ `{{.}} appears in a JS template literal`,
214+ },
215 }
216 for _, test := range tests {
217 buf := new(bytes.Buffer)
218@@ -1304,6 +1308,10 @@ func TestEscapeText(t *testing.T) {
219 context{state: stateJSSqStr, delim: delimDoubleQuote, attr: attrScript},
220 },
221 {
222+ "<a onclick=\"`foo",
223+ context{state: stateJSBqStr, delim: delimDoubleQuote, attr: attrScript},
224+ },
225+ {
226 `<A ONCLICK="'`,
227 context{state: stateJSSqStr, delim: delimDoubleQuote, attr: attrScript},
228 },
229diff --git a/src/html/template/js.go b/src/html/template/js.go
230index ea9c183..b888eaf 100644
231--- a/src/html/template/js.go
232+++ b/src/html/template/js.go
233@@ -308,6 +308,7 @@ var jsStrReplacementTable = []string{
234 // Encode HTML specials as hex so the output can be embedded
235 // in HTML attributes without further encoding.
236 '"': `\u0022`,
237+ '`': `\u0060`,
238 '&': `\u0026`,
239 '\'': `\u0027`,
240 '+': `\u002b`,
241@@ -331,6 +332,7 @@ var jsStrNormReplacementTable = []string{
242 '"': `\u0022`,
243 '&': `\u0026`,
244 '\'': `\u0027`,
245+ '`': `\u0060`,
246 '+': `\u002b`,
247 '/': `\/`,
248 '<': `\u003c`,
249diff --git a/src/html/template/js_test.go b/src/html/template/js_test.go
250index d7ee47b..7d963ae 100644
251--- a/src/html/template/js_test.go
252+++ b/src/html/template/js_test.go
253@@ -292,7 +292,7 @@ func TestEscapersOnLower7AndSelectHighCodepoints(t *testing.T) {
254 `0123456789:;\u003c=\u003e?` +
255 `@ABCDEFGHIJKLMNO` +
256 `PQRSTUVWXYZ[\\]^_` +
257- "`abcdefghijklmno" +
258+ "\\u0060abcdefghijklmno" +
259 "pqrstuvwxyz{|}~\u007f" +
260 "\u00A0\u0100\\u2028\\u2029\ufeff\U0001D11E",
261 },
262diff --git a/src/html/template/jsctx_string.go b/src/html/template/jsctx_string.go
263index dd1d87e..2394893 100644
264--- a/src/html/template/jsctx_string.go
265+++ b/src/html/template/jsctx_string.go
266@@ -4,6 +4,15 @@ package template
267
268 import "strconv"
269
270+func _() {
271+ // An "invalid array index" compiler error signifies that the constant values have changed.
272+ // Re-run the stringer command to generate them again.
273+ var x [1]struct{}
274+ _ = x[jsCtxRegexp-0]
275+ _ = x[jsCtxDivOp-1]
276+ _ = x[jsCtxUnknown-2]
277+}
278+
279 const _jsCtx_name = "jsCtxRegexpjsCtxDivOpjsCtxUnknown"
280
281 var _jsCtx_index = [...]uint8{0, 11, 21, 33}
282diff --git a/src/html/template/state_string.go b/src/html/template/state_string.go
283index 05104be..6fb1a6e 100644
284--- a/src/html/template/state_string.go
285+++ b/src/html/template/state_string.go
286@@ -4,9 +4,42 @@ package template
287
288 import "strconv"
289
290-const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateError"
291+func _() {
292+ // An "invalid array index" compiler error signifies that the constant values have changed.
293+ // Re-run the stringer command to generate them again.
294+ var x [1]struct{}
295+ _ = x[stateText-0]
296+ _ = x[stateTag-1]
297+ _ = x[stateAttrName-2]
298+ _ = x[stateAfterName-3]
299+ _ = x[stateBeforeValue-4]
300+ _ = x[stateHTMLCmt-5]
301+ _ = x[stateRCDATA-6]
302+ _ = x[stateAttr-7]
303+ _ = x[stateURL-8]
304+ _ = x[stateSrcset-9]
305+ _ = x[stateJS-10]
306+ _ = x[stateJSDqStr-11]
307+ _ = x[stateJSSqStr-12]
308+ _ = x[stateJSBqStr-13]
309+ _ = x[stateJSRegexp-14]
310+ _ = x[stateJSBlockCmt-15]
311+ _ = x[stateJSLineCmt-16]
312+ _ = x[stateCSS-17]
313+ _ = x[stateCSSDqStr-18]
314+ _ = x[stateCSSSqStr-19]
315+ _ = x[stateCSSDqURL-20]
316+ _ = x[stateCSSSqURL-21]
317+ _ = x[stateCSSURL-22]
318+ _ = x[stateCSSBlockCmt-23]
319+ _ = x[stateCSSLineCmt-24]
320+ _ = x[stateError-25]
321+ _ = x[stateDead-26]
322+}
323+
324+const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead"
325
326-var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 155, 170, 184, 192, 205, 218, 231, 244, 255, 271, 286, 296}
327+var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 204, 217, 230, 243, 256, 267, 283, 298, 308, 317}
328
329 func (i state) String() string {
330 if i >= state(len(_state_index)-1) {
331diff --git a/src/html/template/transition.go b/src/html/template/transition.go
332index 06df679..92eb351 100644
333--- a/src/html/template/transition.go
334+++ b/src/html/template/transition.go
335@@ -27,6 +27,7 @@ var transitionFunc = [...]func(context, []byte) (context, int){
336 stateJS: tJS,
337 stateJSDqStr: tJSDelimited,
338 stateJSSqStr: tJSDelimited,
339+ stateJSBqStr: tJSDelimited,
340 stateJSRegexp: tJSDelimited,
341 stateJSBlockCmt: tBlockCmt,
342 stateJSLineCmt: tLineCmt,
343@@ -262,7 +263,7 @@ func tURL(c context, s []byte) (context, int) {
344
345 // tJS is the context transition function for the JS state.
346 func tJS(c context, s []byte) (context, int) {
347- i := bytes.IndexAny(s, `"'/`)
348+ i := bytes.IndexAny(s, "\"`'/")
349 if i == -1 {
350 // Entire input is non string, comment, regexp tokens.
351 c.jsCtx = nextJSCtx(s, c.jsCtx)
352@@ -274,6 +275,8 @@ func tJS(c context, s []byte) (context, int) {
353 c.state, c.jsCtx = stateJSDqStr, jsCtxRegexp
354 case '\'':
355 c.state, c.jsCtx = stateJSSqStr, jsCtxRegexp
356+ case '`':
357+ c.state, c.jsCtx = stateJSBqStr, jsCtxRegexp
358 case '/':
359 switch {
360 case i+1 < len(s) && s[i+1] == '/':
361@@ -303,6 +306,8 @@ func tJSDelimited(c context, s []byte) (context, int) {
362 switch c.state {
363 case stateJSSqStr:
364 specials = `\'`
365+ case stateJSBqStr:
366+ specials = "`\\"
367 case stateJSRegexp:
368 specials = `\/[]`
369 }
370--
3712.7.4