mirror of
https://git.yoctoproject.org/poky
synced 2026-07-15 15:37:03 +00:00
go: patch CVE-2026-32289
Backport patch from [1] [1] https://go.dev/cl/763762 (From OE-Core rev: d0469c3a9d62a2ab3d6baef92e578f247d68318b) Signed-off-by: Theo Gaige (Schneider Electric) <tgaige.opensource@witekio.com> Reviewed-by: Bruno Vernay <bruno.vernay@se.com> Signed-off-by: Jeremy Rosen <jeremy.rosen@smile.fr> Signed-off-by: Paul Barker <paul@pbarker.dev>
This commit is contained in:
committed by
Paul Barker
parent
d10a96fbd0
commit
b7967ae307
@@ -44,6 +44,7 @@ SRC_URI += "\
|
||||
file://CVE-2026-27142.patch \
|
||||
file://CVE-2026-32280.patch \
|
||||
file://CVE-2026-32283.patch \
|
||||
file://CVE-2026-32289.patch \
|
||||
"
|
||||
SRC_URI[main.sha256sum] = "012a7e1f37f362c0918c1dfa3334458ac2da1628c4b9cf4d9ca02db986e17d71"
|
||||
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
From 5291c6d3e6d0bc0a764a9a6bd6b3de1be64b8264 Mon Sep 17 00:00:00 2001
|
||||
From: Roland Shoemaker <bracewell@google.com>
|
||||
Date: Mon, 23 Mar 2026 13:34:23 -0700
|
||||
Subject: [PATCH] html/template: properly track JS template literal brace depth
|
||||
across contexts
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Properly track JS template literal brace depth across branches/ranges,
|
||||
and prevent accidental re-use of escape analysis by including the
|
||||
brace depth in the stringification/mangling for contexts.
|
||||
|
||||
Fixes #78331
|
||||
Fixes CVE-2026-32289
|
||||
|
||||
Change-Id: I9f3f47c29e042220b18e4d3299db7a3fae4207fa
|
||||
Reviewed-on: https://go-internal-review.googlesource.com/c/go/+/3882
|
||||
Reviewed-by: Neal Patel <nealpatel@google.com>
|
||||
Reviewed-by: Nicholas Husin <husin@google.com>
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/763762
|
||||
Reviewed-by: Russ Cox <rsc@golang.org>
|
||||
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
|
||||
Auto-Submit: David Chase <drchase@google.com>
|
||||
Reviewed-by: Fan Mỹ Tâm Club <letrivien97@gmail.com>
|
||||
|
||||
CVE: CVE-2026-32289
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/199c4d1c3c9d509a51f777c81cb17d4b17728097]
|
||||
Signed-off-by: Theo Gaige (Schneider Electric) <tgaige.opensource@witekio.com>
|
||||
---
|
||||
src/html/template/context.go | 14 +++++++++++-
|
||||
src/html/template/escape.go | 4 ++--
|
||||
src/html/template/escape_test.go | 38 +++++++++++++++++++++-----------
|
||||
3 files changed, 40 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/src/html/template/context.go b/src/html/template/context.go
|
||||
index 8b3af2feab..132ae2d28d 100644
|
||||
--- a/src/html/template/context.go
|
||||
+++ b/src/html/template/context.go
|
||||
@@ -6,6 +6,7 @@ package template
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
+ "slices"
|
||||
"text/template/parse"
|
||||
)
|
||||
|
||||
@@ -37,7 +38,7 @@ func (c context) String() string {
|
||||
if c.err != nil {
|
||||
err = c.err
|
||||
}
|
||||
- return fmt.Sprintf("{%v %v %v %v %v %v %v}", c.state, c.delim, c.urlPart, c.jsCtx, c.attr, c.element, err)
|
||||
+ return fmt.Sprintf("{%v %v %v %v %v %v %v %v}", c.state, c.delim, c.urlPart, c.jsCtx, c.jsBraceDepth, c.attr, c.element, err)
|
||||
}
|
||||
|
||||
// eq reports whether two contexts are equal.
|
||||
@@ -46,6 +47,7 @@ func (c context) eq(d context) bool {
|
||||
c.delim == d.delim &&
|
||||
c.urlPart == d.urlPart &&
|
||||
c.jsCtx == d.jsCtx &&
|
||||
+ slices.Equal(c.jsBraceDepth, d.jsBraceDepth) &&
|
||||
c.attr == d.attr &&
|
||||
c.element == d.element &&
|
||||
c.err == d.err
|
||||
@@ -68,6 +70,9 @@ func (c context) mangle(templateName string) string {
|
||||
if c.jsCtx != jsCtxRegexp {
|
||||
s += "_" + c.jsCtx.String()
|
||||
}
|
||||
+ if c.jsBraceDepth != nil {
|
||||
+ s += fmt.Sprintf("_jsBraceDepth(%v)", c.jsBraceDepth)
|
||||
+ }
|
||||
if c.attr != attrNone {
|
||||
s += "_" + c.attr.String()
|
||||
}
|
||||
@@ -77,6 +82,13 @@ func (c context) mangle(templateName string) string {
|
||||
return s
|
||||
}
|
||||
|
||||
+// clone returns a copy of c with the same field values.
|
||||
+func (c context) clone() context {
|
||||
+ clone := c
|
||||
+ clone.jsBraceDepth = slices.Clone(c.jsBraceDepth)
|
||||
+ return clone
|
||||
+}
|
||||
+
|
||||
// state describes a high-level HTML parser state.
|
||||
//
|
||||
// It bounds the top of the element stack, and by extension the HTML insertion
|
||||
diff --git a/src/html/template/escape.go b/src/html/template/escape.go
|
||||
index b368cab38c..c031ed27b9 100644
|
||||
--- a/src/html/template/escape.go
|
||||
+++ b/src/html/template/escape.go
|
||||
@@ -522,7 +522,7 @@ func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string)
|
||||
if nodeName == "range" {
|
||||
e.rangeContext = &rangeContext{outer: e.rangeContext}
|
||||
}
|
||||
- c0 := e.escapeList(c, n.List)
|
||||
+ c0 := e.escapeList(c.clone(), n.List)
|
||||
if nodeName == "range" {
|
||||
if c0.state != stateError {
|
||||
c0 = joinRange(c0, e.rangeContext)
|
||||
@@ -553,7 +553,7 @@ func (e *escaper) escapeBranch(c context, n *parse.BranchNode, nodeName string)
|
||||
return c0
|
||||
}
|
||||
}
|
||||
- c1 := e.escapeList(c, n.ElseList)
|
||||
+ c1 := e.escapeList(c.clone(), n.ElseList)
|
||||
return join(c0, c1, n, nodeName)
|
||||
}
|
||||
|
||||
diff --git a/src/html/template/escape_test.go b/src/html/template/escape_test.go
|
||||
index 1970db1695..435c83378f 100644
|
||||
--- a/src/html/template/escape_test.go
|
||||
+++ b/src/html/template/escape_test.go
|
||||
@@ -1181,6 +1181,18 @@ func TestErrors(t *testing.T) {
|
||||
// html is allowed since it is the last command in the pipeline, but urlquery is not.
|
||||
`predefined escaper "urlquery" disallowed in template`,
|
||||
},
|
||||
+ {
|
||||
+ "<script>var a = `{{if .X}}`{{end}}",
|
||||
+ `{{if}} branches end in different contexts`,
|
||||
+ },
|
||||
+ {
|
||||
+ "<script>var a = `{{if .X}}a{{else}}`{{end}}",
|
||||
+ `{{if}} branches end in different contexts`,
|
||||
+ },
|
||||
+ {
|
||||
+ "<script>var a = `{{if .X}}a{{else}}b{{end}}`</script>",
|
||||
+ ``,
|
||||
+ },
|
||||
}
|
||||
for _, test := range tests {
|
||||
buf := new(bytes.Buffer)
|
||||
@@ -1752,7 +1764,7 @@ func TestEscapeText(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"<script>var a = `${",
|
||||
- context{state: stateJS, element: elementScript},
|
||||
+ context{state: stateJS, element: elementScript, jsBraceDepth: []int{0}},
|
||||
},
|
||||
{
|
||||
"<script>var a = `${}",
|
||||
@@ -1760,27 +1772,27 @@ func TestEscapeText(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"<script>var a = `${`",
|
||||
- context{state: stateJSTmplLit, element: elementScript},
|
||||
+ context{state: stateJSTmplLit, element: elementScript, jsBraceDepth: []int{0}},
|
||||
},
|
||||
{
|
||||
"<script>var a = `${var a = \"",
|
||||
- context{state: stateJSDqStr, element: elementScript},
|
||||
+ context{state: stateJSDqStr, element: elementScript, jsBraceDepth: []int{0}},
|
||||
},
|
||||
{
|
||||
"<script>var a = `${var a = \"`",
|
||||
- context{state: stateJSDqStr, element: elementScript},
|
||||
+ context{state: stateJSDqStr, element: elementScript, jsBraceDepth: []int{0}},
|
||||
},
|
||||
{
|
||||
"<script>var a = `${var a = \"}",
|
||||
- context{state: stateJSDqStr, element: elementScript},
|
||||
+ context{state: stateJSDqStr, element: elementScript, jsBraceDepth: []int{0}},
|
||||
},
|
||||
{
|
||||
"<script>var a = `${``",
|
||||
- context{state: stateJS, element: elementScript},
|
||||
+ context{state: stateJS, element: elementScript, jsBraceDepth: []int{0}},
|
||||
},
|
||||
{
|
||||
"<script>var a = `${`}",
|
||||
- context{state: stateJSTmplLit, element: elementScript},
|
||||
+ context{state: stateJSTmplLit, element: elementScript, jsBraceDepth: []int{0}},
|
||||
},
|
||||
{
|
||||
"<script>`${ {} } asd`</script><script>`${ {} }",
|
||||
@@ -1788,7 +1800,7 @@ func TestEscapeText(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"<script>var foo = `${ (_ => { return \"x\" })() + \"${",
|
||||
- context{state: stateJSDqStr, element: elementScript},
|
||||
+ context{state: stateJSDqStr, element: elementScript, jsBraceDepth: []int{0}},
|
||||
},
|
||||
{
|
||||
"<script>var a = `${ {</script><script>var b = `${ x }",
|
||||
@@ -1816,23 +1828,23 @@ func TestEscapeText(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"<script>`${ { `` }",
|
||||
- context{state: stateJS, element: elementScript},
|
||||
+ context{state: stateJS, element: elementScript, jsBraceDepth: []int{0}},
|
||||
},
|
||||
{
|
||||
"<script>`${ { }`",
|
||||
- context{state: stateJSTmplLit, element: elementScript},
|
||||
+ context{state: stateJSTmplLit, element: elementScript, jsBraceDepth: []int{0}},
|
||||
},
|
||||
{
|
||||
"<script>var foo = `${ foo({ a: { c: `${",
|
||||
- context{state: stateJS, element: elementScript},
|
||||
+ context{state: stateJS, element: elementScript, jsBraceDepth: []int{2, 0}},
|
||||
},
|
||||
{
|
||||
"<script>var foo = `${ foo({ a: { c: `${ {{.}} }` }, b: ",
|
||||
- context{state: stateJS, element: elementScript},
|
||||
+ context{state: stateJS, element: elementScript, jsBraceDepth: []int{1}},
|
||||
},
|
||||
{
|
||||
"<script>`${ `}",
|
||||
- context{state: stateJSTmplLit, element: elementScript},
|
||||
+ context{state: stateJSTmplLit, element: elementScript, jsBraceDepth: []int{0}},
|
||||
},
|
||||
}
|
||||
|
||||
--
|
||||
2.43.0
|
||||
|
||||
Reference in New Issue
Block a user