summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/go/go-1.14/CVE-2023-39319.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/go/go-1.14/CVE-2023-39319.patch')
-rw-r--r--meta/recipes-devtools/go/go-1.14/CVE-2023-39319.patch230
1 files changed, 230 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-39319.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-39319.patch
new file mode 100644
index 0000000000..69106e3e05
--- /dev/null
+++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-39319.patch
@@ -0,0 +1,230 @@
1From 2070531d2f53df88e312edace6c8dfc9686ab2f5 Mon Sep 17 00:00:00 2001
2From: Roland Shoemaker <bracewell@google.com>
3Date: Thu, 3 Aug 2023 12:28:28 -0700
4Subject: [PATCH] [release-branch.go1.20] html/template: properly handle
5 special tags within the script context
6
7The HTML specification has incredibly complex rules for how to handle
8"<!--", "<script", and "</script" when they appear within literals in
9the script context. Rather than attempting to apply these restrictions
10(which require a significantly more complex state machine) we apply
11the workaround suggested in section 4.12.1.3 of the HTML specification [1].
12
13More precisely, when "<!--", "<script", and "</script" appear within
14literals (strings and regular expressions, ignoring comments since we
15already elide their content) we replace the "<" with "\x3C". This avoids
16the unintuitive behavior that using these tags within literals can cause,
17by simply preventing the rendered content from triggering it. This may
18break some correct usages of these tags, but on balance is more likely
19to prevent XSS attacks where users are unknowingly either closing or not
20closing the script blocks where they think they are.
21
22Thanks to Takeshi Kaneko (GMO Cybersecurity by Ierae, Inc.) for
23reporting this issue.
24
25Fixes #62197
26Fixes #62397
27Fixes CVE-2023-39319
28
29[1] https://html.spec.whatwg.org/#restrictions-for-contents-of-script-elements
30
31Change-Id: Iab57b0532694827e3eddf57a7497ba1fab1746dc
32Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1976594
33Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
34Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
35Reviewed-by: Damien Neil <dneil@google.com>
36Run-TryBot: Roland Shoemaker <bracewell@google.com>
37Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/2014621
38TryBot-Result: Security TryBots <security-trybots@go-security-trybots.iam.gserviceaccount.com>
39Reviewed-on: https://go-review.googlesource.com/c/go/+/526099
40TryBot-Result: Gopher Robot <gobot@golang.org>
41Run-TryBot: Cherry Mui <cherryyz@google.com>
42
43Upstream-Status: Backport from [https://github.com/golang/go/commit/2070531d2f53df88e312edace6c8dfc9686ab2f5]
44CVE: CVE-2023-39319
45Signed-off-by: Siddharth Doshi <sdoshi@mvista.com>
46---
47 src/html/template/context.go | 14 ++++++++++
48 src/html/template/escape.go | 26 ++++++++++++++++++
49 src/html/template/escape_test.go | 47 +++++++++++++++++++++++++++++++-
50 src/html/template/transition.go | 15 ++++++++++
51 4 files changed, 101 insertions(+), 1 deletion(-)
52
53diff --git a/src/html/template/context.go b/src/html/template/context.go
54index 4eb7891..feb6517 100644
55--- a/src/html/template/context.go
56+++ b/src/html/template/context.go
57@@ -168,6 +168,20 @@ func isInTag(s state) bool {
58 return false
59 }
60
61+// isInScriptLiteral returns true if s is one of the literal states within a
62+// <script> tag, and as such occurances of "<!--", "<script", and "</script"
63+// need to be treated specially.
64+func isInScriptLiteral(s state) bool {
65+ // Ignore the comment states (stateJSBlockCmt, stateJSLineCmt,
66+ // stateJSHTMLOpenCmt, stateJSHTMLCloseCmt) because their content is already
67+ // omitted from the output.
68+ switch s {
69+ case stateJSDqStr, stateJSSqStr, stateJSBqStr, stateJSRegexp:
70+ return true
71+ }
72+ return false
73+}
74+
75 // delim is the delimiter that will end the current HTML attribute.
76 type delim uint8
77
78diff --git a/src/html/template/escape.go b/src/html/template/escape.go
79index ad2ec69..de8cf6f 100644
80--- a/src/html/template/escape.go
81+++ b/src/html/template/escape.go
82@@ -10,6 +10,7 @@ import (
83 "html"
84 "internal/godebug"
85 "io"
86+ "regexp"
87 "text/template"
88 "text/template/parse"
89 )
90@@ -650,6 +651,26 @@ var delimEnds = [...]string{
91 delimSpaceOrTagEnd: " \t\n\f\r>",
92 }
93
94+var (
95+ // Per WHATWG HTML specification, section 4.12.1.3, there are extremely
96+ // complicated rules for how to handle the set of opening tags <!--,
97+ // <script, and </script when they appear in JS literals (i.e. strings,
98+ // regexs, and comments). The specification suggests a simple solution,
99+ // rather than implementing the arcane ABNF, which involves simply escaping
100+ // the opening bracket with \x3C. We use the below regex for this, since it
101+ // makes doing the case-insensitive find-replace much simpler.
102+ specialScriptTagRE = regexp.MustCompile("(?i)<(script|/script|!--)")
103+ specialScriptTagReplacement = []byte("\\x3C$1")
104+)
105+
106+func containsSpecialScriptTag(s []byte) bool {
107+ return specialScriptTagRE.Match(s)
108+}
109+
110+func escapeSpecialScriptTags(s []byte) []byte {
111+ return specialScriptTagRE.ReplaceAll(s, specialScriptTagReplacement)
112+}
113+
114 var doctypeBytes = []byte("<!DOCTYPE")
115
116 // escapeText escapes a text template node.
117@@ -708,6 +729,11 @@ func (e *escaper) escapeText(c context, n *parse.TextNode) context {
118 b.Write(s[written:cs])
119 written = i1
120 }
121+ if isInScriptLiteral(c.state) && containsSpecialScriptTag(s[i:i1]) {
122+ b.Write(s[written:i])
123+ b.Write(escapeSpecialScriptTags(s[i:i1]))
124+ written = i1
125+ }
126 if i == i1 && c.state == c1.state {
127 panic(fmt.Sprintf("infinite loop from %v to %v on %q..%q", c, c1, s[:i], s[i:]))
128 }
129diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
130index 5f41e52..0cacb20 100644
131--- a/src/html/template/escape_test.go
132+++ b/src/html/template/escape_test.go
133@@ -513,6 +513,21 @@ func TestEscape(t *testing.T) {
134 "<script>#! beep\n</script>",
135 "<script>\n</script>",
136 },
137+ {
138+ "Special tags in <script> string literals",
139+ `<script>var a = "asd < 123 <!-- 456 < fgh <script jkl < 789 </script"</script>`,
140+ `<script>var a = "asd < 123 \x3C!-- 456 < fgh \x3Cscript jkl < 789 \x3C/script"</script>`,
141+ },
142+ {
143+ "Special tags in <script> string literals (mixed case)",
144+ `<script>var a = "<!-- <ScripT </ScripT"</script>`,
145+ `<script>var a = "\x3C!-- \x3CScripT \x3C/ScripT"</script>`,
146+ },
147+ {
148+ "Special tags in <script> regex literals (mixed case)",
149+ `<script>var a = /<!-- <ScripT </ScripT/</script>`,
150+ `<script>var a = /\x3C!-- \x3CScripT \x3C/ScripT/</script>`,
151+ },
152 {
153 "CSS comments",
154 "<style>p// paragraph\n" +
155@@ -1501,8 +1516,38 @@ func TestEscapeText(t *testing.T) {
156 context{state: stateJS, element: elementScript},
157 },
158 {
159+ // <script and </script tags are escaped, so </script> should not
160+ // cause us to exit the JS state.
161 `<script>document.write("<script>alert(1)</script>");`,
162- context{state: stateText},
163+ context{state: stateJS, element: elementScript},
164+ },
165+ {
166+ `<script>document.write("<script>`,
167+ context{state: stateJSDqStr, element: elementScript},
168+ },
169+ {
170+ `<script>document.write("<script>alert(1)</script>`,
171+ context{state: stateJSDqStr, element: elementScript},
172+ },
173+ {
174+ `<script>document.write("<script>alert(1)<!--`,
175+ context{state: stateJSDqStr, element: elementScript},
176+ },
177+ {
178+ `<script>document.write("<script>alert(1)</Script>");`,
179+ context{state: stateJS, element: elementScript},
180+ },
181+ {
182+ `<script>document.write("<!--");`,
183+ context{state: stateJS, element: elementScript},
184+ },
185+ {
186+ `<script>let a = /</script`,
187+ context{state: stateJSRegexp, element: elementScript},
188+ },
189+ {
190+ `<script>let a = /</script/`,
191+ context{state: stateJS, element: elementScript, jsCtx: jsCtxDivOp},
192 },
193 {
194 `<script type="text/template">`,
195diff --git a/src/html/template/transition.go b/src/html/template/transition.go
196index 12aa4c4..3d2a37c 100644
197--- a/src/html/template/transition.go
198+++ b/src/html/template/transition.go
199@@ -214,6 +214,11 @@ var (
200 // element states.
201 func tSpecialTagEnd(c context, s []byte) (context, int) {
202 if c.element != elementNone {
203+ // script end tags ("</script") within script literals are ignored, so that
204+ // we can properly escape them.
205+ if c.element == elementScript && (isInScriptLiteral(c.state) || isComment(c.state)) {
206+ return c, len(s)
207+ }
208 if i := indexTagEnd(s, specialTagEndMarkers[c.element]); i != -1 {
209 return context{}, i
210 }
211@@ -353,6 +358,16 @@ func tJSDelimited(c context, s []byte) (context, int) {
212 inCharset = true
213 case ']':
214 inCharset = false
215+ case '/':
216+ // If "</script" appears in a regex literal, the '/' should not
217+ // close the regex literal, and it will later be escaped to
218+ // "\x3C/script" in escapeText.
219+ if i > 0 && i+7 <= len(s) && bytes.Compare(bytes.ToLower(s[i-1:i+7]), []byte("</script")) == 0 {
220+ i++
221+ } else if !inCharset {
222+ c.state, c.jsCtx = stateJS, jsCtxDivOp
223+ return c, i + 1
224+ }
225 default:
226 // end delimiter
227 if !inCharset {
228--
2292.24.4
230