mirror of
https://github.com/golang/go.git
synced 2025-05-05 15:43:04 +00:00
html/template: escape script tags in JS errors case insensitively
Thanks to Juho Forsén of Mattermost for reporting this issue. Fixes #70740 Change-Id: I1a49b199dee91cd2bb4df5b174aaa958dc040c18 Reviewed-on: https://go-review.googlesource.com/c/go/+/634696 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
parent
fce17b0c77
commit
e6de1b2deb
@ -9,6 +9,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
)
|
||||||
@ -144,6 +145,8 @@ func indirectToJSONMarshaler(a any) any {
|
|||||||
return v.Interface()
|
return v.Interface()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var scriptTagRe = regexp.MustCompile("(?i)<(/?)script")
|
||||||
|
|
||||||
// jsValEscaper escapes its inputs to a JS Expression (section 11.14) that has
|
// jsValEscaper escapes its inputs to a JS Expression (section 11.14) that has
|
||||||
// neither side-effects nor free variables outside (NaN, Infinity).
|
// neither side-effects nor free variables outside (NaN, Infinity).
|
||||||
func jsValEscaper(args ...any) string {
|
func jsValEscaper(args ...any) string {
|
||||||
@ -181,9 +184,9 @@ func jsValEscaper(args ...any) string {
|
|||||||
// In particular we:
|
// In particular we:
|
||||||
// * replace "*/" comment end tokens with "* /", which does not
|
// * replace "*/" comment end tokens with "* /", which does not
|
||||||
// terminate the comment
|
// terminate the comment
|
||||||
// * replace "</script" with "\x3C/script", and "<!--" with
|
// * replace "<script" and "</script" with "\x3Cscript" and "\x3C/script"
|
||||||
// "\x3C!--", which prevents confusing script block termination
|
// (case insensitively), and "<!--" with "\x3C!--", which prevents
|
||||||
// semantics
|
// confusing script block termination semantics
|
||||||
//
|
//
|
||||||
// We also put a space before the comment so that if it is flush against
|
// We also put a space before the comment so that if it is flush against
|
||||||
// a division operator it is not turned into a line comment:
|
// a division operator it is not turned into a line comment:
|
||||||
@ -192,8 +195,8 @@ func jsValEscaper(args ...any) string {
|
|||||||
// x//* error marshaling y:
|
// x//* error marshaling y:
|
||||||
// second line of error message */null
|
// second line of error message */null
|
||||||
errStr := err.Error()
|
errStr := err.Error()
|
||||||
|
errStr = string(scriptTagRe.ReplaceAll([]byte(errStr), []byte(`\x3C${1}script`)))
|
||||||
errStr = strings.ReplaceAll(errStr, "*/", "* /")
|
errStr = strings.ReplaceAll(errStr, "*/", "* /")
|
||||||
errStr = strings.ReplaceAll(errStr, "</script", `\x3C/script`)
|
|
||||||
errStr = strings.ReplaceAll(errStr, "<!--", `\x3C!--`)
|
errStr = strings.ReplaceAll(errStr, "<!--", `\x3C!--`)
|
||||||
return fmt.Sprintf(" /* %s */null ", errStr)
|
return fmt.Sprintf(" /* %s */null ", errStr)
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ func TestNextJsCtx(t *testing.T) {
|
|||||||
type jsonErrType struct{}
|
type jsonErrType struct{}
|
||||||
|
|
||||||
func (e *jsonErrType) MarshalJSON() ([]byte, error) {
|
func (e *jsonErrType) MarshalJSON() ([]byte, error) {
|
||||||
return nil, errors.New("beep */ boop </script blip <!--")
|
return nil, errors.New("a */ b <script c </script d <!-- e <sCrIpT f </sCrIpT")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestJSValEscaper(t *testing.T) {
|
func TestJSValEscaper(t *testing.T) {
|
||||||
@ -160,7 +160,7 @@ func TestJSValEscaper(t *testing.T) {
|
|||||||
{"</script", `"\u003c/script"`, false},
|
{"</script", `"\u003c/script"`, false},
|
||||||
{"\U0001D11E", "\"\U0001D11E\"", false}, // or "\uD834\uDD1E"
|
{"\U0001D11E", "\"\U0001D11E\"", false}, // or "\uD834\uDD1E"
|
||||||
{nil, " null ", false},
|
{nil, " null ", false},
|
||||||
{&jsonErrType{}, " /* json: error calling MarshalJSON for type *template.jsonErrType: beep * / boop \\x3C/script blip \\x3C!-- */null ", true},
|
{&jsonErrType{}, " /* json: error calling MarshalJSON for type *template.jsonErrType: a * / b \\x3Cscript c \\x3C/script d \\x3C!-- e \\x3Cscript f \\x3C/script */null ", true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user