Skip to content

Commit 51727b4

Browse files
committed
added case-insensitive escaping for script tag
1 parent 20e1a67 commit 51727b4

File tree

3 files changed

+16
-10
lines changed

3 files changed

+16
-10
lines changed

elements.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,8 +253,8 @@ func Meta(attrs attrs.Props) *Element {
253253
}
254254

255255
// Script creates a <script> element.
256-
// According to https://html.spec.whatwg.org/multipage/scripting.html#the-script-element, only text nodes are allowed inside the <script> element.
257-
// Additionally, if the src attribute is present, children must be either empty or contain only comments. However, the original version of this function
256+
// According to https://html.spec.whatwg.org/multipage/scripting.html#the-script-element, no tags or comments are allowed inside the <script> element.
257+
// Additionally, if the src attribute is present, children must be either empty or contain only script comments. However, the original version of this function
258258
// allowed the use of any number of arbitrary elements. This is left as-is for backwards compatibility.
259259
func Script(attrs attrs.Props, children ...Node) *Element {
260260
// Transform children to ScriptNodes to implement content escaping

elements_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,10 @@ func TestScriptEscaping(t *testing.T) {
368368
el = Script(attrs.Props{}, Raw(`alert("<script> and </script> tags must be properly escaped");`))
369369
assert.Equal(t, expected, el.Render())
370370

371+
expected = `<script>alert("\x3CScripT> and \x3C/ScRiPt> are case-insensitive");</script>`
372+
el = Script(attrs.Props{}, Raw(`alert("<ScripT> and </ScRiPt> are case-insensitive");`))
373+
assert.Equal(t, expected, el.Render())
374+
371375
expected = `<script>alert("\x3C!-- comment openings must be escaped too");</script>`
372376
el = Script(attrs.Props{}, Raw(`alert("<!-- comment openings must be escaped too");`))
373377
assert.Equal(t, expected, el.Render())

utils.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package elem
22

3-
import "strings"
3+
import (
4+
"regexp"
5+
"strings"
6+
)
47

58
// nodeContentReplacer handles escaping of HTML special characters in text nodes
69
// note that single and double quotes (', ") do not need escaping in HTML5 text nodes
@@ -18,12 +21,6 @@ var commentContentsReplacer = strings.NewReplacer(
1821
"--!>", "--!&gt;",
1922
)
2023

21-
var scriptContentsReplaces = strings.NewReplacer(
22-
"<!--", "\\x3C!--",
23-
"<script", "\\x3Cscript",
24-
"</script", "\\x3C/script",
25-
)
26-
2724
// If conditionally renders one of the provided elements based on the condition
2825
func If[T any](condition bool, ifTrue, ifFalse T) T {
2926
if condition {
@@ -74,7 +71,12 @@ func EscapeCommentContents(s string) string {
7471
return s
7572
}
7673

74+
// scriptContentsRegexp matches <script and </script case-insensitively
75+
var scriptContentsRegexp = regexp.MustCompile(`(?i)<(/?)(script)`)
76+
7777
// EscapeScriptContents escapes the contents of a script node according to https://html.spec.whatwg.org/multipage/scripting.html#restrictions-for-contents-of-script-elements
7878
func EscapeScriptContents(s string) string {
79-
return scriptContentsReplaces.Replace(s)
79+
s = strings.ReplaceAll(s, `<!--`, `\x3C!--`)
80+
s = scriptContentsRegexp.ReplaceAllString(s, `\x3C$1$2`)
81+
return s
8082
}

0 commit comments

Comments
 (0)