Unescaping HTML in html/template

13,948 views
Skip to first unread message

Ryan Kohler

unread,
Apr 8, 2012, 8:54:53 PM4/8/12
to golan...@googlegroups.com
Is there any way I can, within a template, specify certain sections to allow unsafe insertion?  e.g.:

T.execute(w, vars)
where

T :=
<html>
    <head>
        <title>{{.Title}}</title>
    </head>
    <body>
        {{unsafe .Body}}
    </body>
</html>

vars := map[string] interface {} {"Title":"Test","Body":"Hello <b>World</b>"}

html/template assumes that all of the inputs are unsafe, but if I know that Body is safe, what can I do?
I understand that if I typed Body as an HTML instead of a string, it could work, but if it's part of a map, I seem to have trouble getting the template engine to distinguish between the types.  Perhaps I'm doing something wrong

Devon H. O'Dell

unread,
Apr 8, 2012, 9:00:28 PM4/8/12
to Ryan Kohler, golan...@googlegroups.com
Op 8 april 2012 20:54 heeft Ryan Kohler <ryan.c...@gmail.com> het
volgende geschreven:

My solution has been to make Title and Body methods on ., and making
Body() return template.HTML while Title() just returns string. These
functions then know where to get the data, which can at that point all
come from the map you have defined.

--dho

Nigel Tao

unread,
Apr 8, 2012, 9:22:31 PM4/8/12
to Ryan Kohler, golan...@googlegroups.com
vars := map[string] interface {} {
"Title":"Test",
"Body":template.HTML("Hello <b>World</b>"),
}

http://play.golang.org/p/Uw8l3M7Qvg

Ryan Kohler

unread,
Apr 8, 2012, 9:48:00 PM4/8/12
to golan...@googlegroups.com, Ryan Kohler
Thanks for the tip!

It looks like everything works fine as long as it gets stored into the map as type template.HTML

In my case, I was doing some type checking that I had forgot about to make sure that the body was a string, so when I tried to change it to a template.HTML, it couldn't find a string, assumed that it wasn't found and overwrote it

Ryan Kohler

unread,
Apr 8, 2012, 9:48:45 PM4/8/12
to golan...@googlegroups.com, Ryan Kohler
Thank you!

David Symonds

unread,
Apr 9, 2012, 12:34:12 AM4/9/12
to Ryan Kohler, golan...@googlegroups.com
There's also the "noescape" function that is, for some reason, undocumented.

{{.Body | noescape}}

Mike Samuel

unread,
Apr 13, 2012, 10:00:03 PM4/13/12
to golang-nuts


On Apr 9, 12:34 am, David Symonds <dsymo...@golang.org> wrote:
> There's also the "noescape" function that is, for some reason, undocumented.
>
> {{.Body | noescape}}

This is correct. It's meant to allow for auditable exceptions to the
rule.

The problem with |noescape is that it's not type-safe.

<title>{{.KnownSafeHtml |noescape}}</title>

is probably fine, but

<a href="{{.KnownSafeHtml |noescape}}">

is not since not every string of innocuous HTML is an innocuous URL.
E.g. "javascript:alert(1337)" contains no side-effects when parsed as
HTML, but does when interpreted as a URL.

If you're writing new code (instead of migrating), I'd recommend using
template.HTML as Nigel suggests or one of the other safe content types
defined at http://code.google.com/p/go/source/browse/src/pkg/html/template/content.go

For example, if you've got known-safe HTML coming from a template or
from an HTML sanitizer, just use the template.HTML type. If you've
got a known-safe URL, use template.URL.

Do this consistently and you're less vulnerable.

Finally, I'm a little confused as to why you would do this
specifically with <title>. <title> can't contain tags, only entities,
so there's really no value in pre-escaping the content of <title>.

Russ Cox

unread,
Apr 18, 2012, 12:50:16 PM4/18/12
to Mike Samuel, golang-nuts
noescape is undocumented and requires explicit registration to enable.
I expect that it might well be removed in Go 1.1.
Reply all
Reply to author
Forward
0 new messages