diff --git a/src/html/template/js.go b/src/html/template/js.go
index b159af8e4b..d911ada26d 100644
--- a/src/html/template/js.go
+++ b/src/html/template/js.go
@@ -171,13 +171,31 @@ func jsValEscaper(args ...any) string {
// cyclic data. This may be an unacceptable DoS risk.
b, err := json.Marshal(a)
if err != nil {
- // Put a space before comment so that if it is flush against
+ // While the standard JSON marshaller does not include user controlled
+ // information in the error message, if a type has a MarshalJSON method,
+ // the content of the error message is not guaranteed. Since we insert
+ // the error into the template, as part of a comment, we attempt to
+ // prevent the error from either terminating the comment, or the script
+ // block itself.
+ //
+ // In particular we:
+ // * replace "*/" comment end tokens with "* /", which does not
+ // terminate the comment
+ // * replace " 1 so this loses precision in JS
// but it is still a representable integer literal.
- {uint64(1)<<53 + 1, " 9007199254740993 "},
- {float32(1.0), " 1 "},
- {float32(-1.0), " -1 "},
- {float32(0.5), " 0.5 "},
- {float32(-0.5), " -0.5 "},
- {float32(1.0) / float32(256), " 0.00390625 "},
- {float32(0), " 0 "},
- {math.Copysign(0, -1), " -0 "},
- {float64(1.0), " 1 "},
- {float64(-1.0), " -1 "},
- {float64(0.5), " 0.5 "},
- {float64(-0.5), " -0.5 "},
- {float64(0), " 0 "},
- {math.Copysign(0, -1), " -0 "},
- {"", `""`},
- {"foo", `"foo"`},
+ {uint64(1)<<53 + 1, " 9007199254740993 ", false},
+ {float32(1.0), " 1 ", false},
+ {float32(-1.0), " -1 ", false},
+ {float32(0.5), " 0.5 ", false},
+ {float32(-0.5), " -0.5 ", false},
+ {float32(1.0) / float32(256), " 0.00390625 ", false},
+ {float32(0), " 0 ", false},
+ {math.Copysign(0, -1), " -0 ", false},
+ {float64(1.0), " 1 ", false},
+ {float64(-1.0), " -1 ", false},
+ {float64(0.5), " 0.5 ", false},
+ {float64(-0.5), " -0.5 ", false},
+ {float64(0), " 0 ", false},
+ {math.Copysign(0, -1), " -0 ", false},
+ {"", `""`, false},
+ {"foo", `"foo"`, false},
// Newlines.
- {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`},
+ {"\r\n\u2028\u2029", `"\r\n\u2028\u2029"`, false},
// "\v" == "v" on IE 6 so use "\u000b" instead.
- {"\t\x0b", `"\t\u000b"`},
- {struct{ X, Y int }{1, 2}, `{"X":1,"Y":2}`},
- {[]any{}, "[]"},
- {[]any{42, "foo", nil}, `[42,"foo",null]`},
- {[]string{""}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`},
- {"", `"--\u003e"`},
- {"", `"]]\u003e"`},
- {"", "-->"}, `["\u003c!--","\u003c/script\u003e","--\u003e"]`, false},
+ {"", `"--\u003e"`, false},
+ {"", `"]]\u003e"`, false},
+ {"