html/template strips conditional comments from HTML

3,024 views
Skip to first unread message

Vladimir Mihailenco

unread,
Mar 31, 2012, 7:52:38 AM3/31/12
to golang-nuts
html/template strips HTML comments from template. That may be ok, but
it also strips conditional comments like this:

<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/
html5.js"></script>
<![endif]-->

, which breaks markup. Example: http://play.golang.org/p/Ybyo-0CDqq .
Is it done intentional?

Kyle Lemons

unread,
Mar 31, 2012, 5:01:35 PM3/31/12
to Vladimir Mihailenco, golang-nuts
Yes.

If it didn't, it would have to understand the idiosyncrasies of any possible such format (I believe that one is IE specific) in order to properly define the context of any enclosed or subsequent HTML.

Vladimir Mihailenco

unread,
Apr 1, 2012, 4:30:08 AM4/1/12
to Kyle Lemons, golang-nuts
Actually authors bothered to parse comments and strip them. So html/template already understands what comments are. Can html/template be changed to don't strip comments and treat them like ordinary HTML (which they are part of: http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.4)?


>the idiosyncrasies of any possible such format
Such idiosyncrasy is required in order to use Twitter Bootstrap, which is both very popular and modern.

David Symonds

unread,
Apr 1, 2012, 6:16:48 AM4/1/12
to Vladimir Mihailenco, golang-nuts, Kyle Lemons

On Apr 1, 2012 6:30 PM, "Vladimir Mihailenco" <vladimi...@gmail.com> wrote:

> Actually authors bothered to parse comments and strip them. So html/template already understands what comments are. Can html/template be changed to don't strip comments and treat them like ordinary HTML (which they are part of: http://www.w3.org/TR/html4/intro/sgmltut.html#h-3.2.4)?

That would not be safe. html/template needs to know the proper context at each point of the template evaluation, but these types of comments cause their contents to be in a browser-dependent context, so the autoescaping can not be done reliably.

Are there other autoescaping template systems that preserve comments?

Dave.

Vladimir Mihailenco

unread,
Apr 1, 2012, 10:17:12 AM4/1/12
to David Symonds, golang-nuts, Kyle Lemons

That would not be safe. html/template needs to know the proper context at each point of the template evaluation, but these types of comments cause their contents to be in a browser-dependent context, so the autoescaping can not be done reliably.

Could you give an example of the comment that can not be properly autoescaped please?

TBH I don't understand why my HTML was stripped and how this affects security:

>This package assumes that template authors are trusted, that Execute's data parameter is not, and seeks to preserve the properties below in the face of untrusted data:


>Are there other autoescaping template systems that preserve comments?
I don't know any that strip them by default. And they also don't try to do any context specific escaping, but that does not stop them to render comments.

Kyle Lemons

unread,
Apr 1, 2012, 12:10:55 PM4/1/12
to Vladimir Mihailenco, David Symonds, golang-nuts
On Sun, Apr 1, 2012 at 7:17 AM, Vladimir Mihailenco <vladimi...@gmail.com> wrote:

That would not be safe. html/template needs to know the proper context at each point of the template evaluation, but these types of comments cause their contents to be in a browser-dependent context, so the autoescaping can not be done reliably.

Could you give an example of the comment that can not be properly autoescaped please?

<p>
<!--[if lt IE 9]><script><![endif]-->
{{.Stuff}}
<!--[if lt IE 9]></script><![endif]-->
</p>

Vladimir Mihailenco

unread,
Apr 1, 2012, 1:50:25 PM4/1/12
to Kyle Lemons, David Symonds, golang-nuts
<p>
<!--[if lt IE 9]><script><![endif]-->
{{.Stuff}}
<!--[if lt IE 9]></script><![endif]-->
</p>
Thanks. It does not work for me in IE 6, but probably I have wrong IE version. I tried:

<!--[if lt IE 9]><script><![endif]-->alert("works!");<!--[if lt IE 9]></script><![endif]-->

And even if it works I will not consider it html/template package issue.

bugpowder

unread,
Apr 1, 2012, 2:51:43 PM4/1/12
to golan...@googlegroups.com, Vladimir Mihailenco, David Symonds
On Monday, April 2, 2012 12:10:55 AM UTC+8, Kyle Lemons wrote:
On Sun, Apr 1, 2012 at 7:17 AM, Vladimir Mihailenco <vladimi...@gmail.com> wrote:

That would not be safe. html/template needs to know the proper context at each point of the template evaluation, but these types of comments cause their contents to be in a browser-dependent context, so the autoescaping can not be done reliably.

Could you give an example of the comment that can not be properly autoescaped please?

<p>
<!--[if lt IE 9]><script><![endif]-->
{{.Stuff}}
<!--[if lt IE 9]></script><![endif]-->
</p>

It's not the template's job to make assumptions about what I intend in this case --or even to try to be aware of the context in this case. 

Conditional comments should be preserved, else the template package would be unfit for many real world uses. 

Devon H. O'Dell

unread,
Apr 1, 2012, 3:00:43 PM4/1/12
to bugpowder, golan...@googlegroups.com, Vladimir Mihailenco, David Symonds
Op 1 april 2012 14:51 heeft bugpowder <mit...@gmail.com> het volgende
geschreven:

> On Monday, April 2, 2012 12:10:55 AM UTC+8, Kyle Lemons wrote:
>>
>> On Sun, Apr 1, 2012 at 7:17 AM, Vladimir Mihailenco
>> <vladimi...@gmail.com> wrote:
>>>>
>>>> That would not be safe. html/template needs to know the proper context
>>>> at each point of the template evaluation, but these types of comments cause
>>>> their contents to be in a browser-dependent context, so the autoescaping can
>>>> not be done reliably.
>>>
>>> Could you give an example of the comment that can not be properly
>>> autoescaped please?
>>
>>
>> <p>
>> <!--[if lt IE 9]><script><![endif]-->
>> {{.Stuff}}
>> <!--[if lt IE 9]></script><![endif]-->
>> </p>
>
>
> It's not the template's job to make assumptions about what I intend in this
> case --or even to try to be aware of the context in this case.

You do realize that the template/html package does not escape HTML
that is of type html.HTML, right? Assuming your comments are coming
from something like {{ .HeaderMethod }}, just make HeaderMethod return
type html.HTML and return html.HTML("<!--comment-->") instead of just
"<!--comment-->"

Kyle Lemons

unread,
Apr 1, 2012, 4:12:04 PM4/1/12
to bugpowder, golan...@googlegroups.com, Vladimir Mihailenco, David Symonds
On Sun, Apr 1, 2012 at 11:51 AM, bugpowder <mit...@gmail.com> wrote:
On Monday, April 2, 2012 12:10:55 AM UTC+8, Kyle Lemons wrote:
On Sun, Apr 1, 2012 at 7:17 AM, Vladimir Mihailenco <vladimi...@gmail.com> wrote:

That would not be safe. html/template needs to know the proper context at each point of the template evaluation, but these types of comments cause their contents to be in a browser-dependent context, so the autoescaping can not be done reliably.

Could you give an example of the comment that can not be properly autoescaped please?

<p>
<!--[if lt IE 9]><script><![endif]-->
{{.Stuff}}
<!--[if lt IE 9]></script><![endif]-->
</p>

It's not the template's job to make assumptions about what I intend in this case --or even to try to be aware of the context in this case. 

Conditional comments should be preserved, else the template package would be unfit for many real world uses. 
In addition to Devon's suggestion for a workaround, I think you may have missed the point of the html/template package.  If you want simple textual templates, use text/template.  The express purpose of html/template is to do context-sensitive autoescaping, which is impossible in the above case unless (a) the template parser understands every possible conditional comment and (b) the template execution engine is aware of how the browser will interpret the code.  In practice, both of these are not feasible.

Andy Balholm

unread,
Apr 2, 2012, 8:48:41 AM4/2/12
to golan...@googlegroups.com, bugpowder, Vladimir Mihailenco, David Symonds
I don't understand why you need conditional comments in dynamically-generated HTML. Look at the user-agent string, detect the browser version, and make your template generate the HTML that the particular browser needs.

Maybe this approach would cause problems for caching, but if your page is dynamically generated, it probably shouldn't be cached anyway.

This approach seems much cleaner, and it could also be extended to apply to other browsers besides IE.

Bugpowder

unread,
Apr 2, 2012, 11:24:17 AM4/2/12
to Andy Balholm, golan...@googlegroups.com, Vladimir Mihailenco, David Symonds
On Apr 2, 2012, at 20:48, Andy Balholm <andyb...@gmail.com> wrote:

> I don't understand why you need conditional comments in dynamically-generated HTML. Look at the user-agent string, detect the browser version, and make your template generate the HTML that the particular browser needs.

You could be using it offline.

Also there is caching, yes

Mike Samuel

unread,
Apr 2, 2012, 9:19:04 PM4/2/12
to golang-nuts


On Mar 31, 7:52 am, Vladimir Mihailenco <vladimir.web...@gmail.com>
wrote:
html/template strips comments because analysis of one codebase showed
that comments often contained code that the template authors had
disabled or contained comments that template authors intended for
reviewers and maintainers and did not intend to expose to larger
audiences, and because properly handling HTML <!--[...]-->, JS /
*@cc_on ... */, and CSS's occasionally nesting comments properly
requires introducing output-language-specific conditional constructs
which is just a headache. Instead I decided just to handle the core
languages.

If you want to embed conditional compilation comments, you can do

{{noescape "<!--[if lt IE 9]>"}}
   <script src="http://html5shim.googlecode.com/svn/trunk html5.js"></
script>
{{noescape "<![endif]-->"}}

or you can put the text of the comment in a safe html value and
introduce it as data.

Kevin Ballard

unread,
Apr 2, 2012, 9:52:52 PM4/2/12
to Andy Balholm, golan...@googlegroups.com, bugpowder, Vladimir Mihailenco, David Symonds
On Mon, Apr 2, 2012 at 5:48 AM, Andy Balholm <andyb...@gmail.com> wrote:
I don't understand why you need conditional comments in dynamically-generated HTML. Look at the user-agent string, detect the browser version, and make your template generate the HTML that the particular browser needs.

Oh dear god no. This is not what the user agent string is for. Browsers can, and do, lie about what they are. The rendering of a page should never depend on its user agent string.

--
Kevin Ballard
http://kevin.sb.org
kbal...@gmail.com

Sanjay Menakuru

unread,
Apr 2, 2012, 10:11:23 PM4/2/12
to golan...@googlegroups.com, Andy Balholm, bugpowder, Vladimir Mihailenco, David Symonds
What are user agent strings for?

I compile different scripts per rendering engine, and one "general-purpose" one. If UA string is unlike any predefined patterns, I serve the general one. Further, the specific ones confirm that they are running on the right platform when they execute, and if not, they fallback to the general script.

I've never seen any browsers "lie" about their user agent, what do you mean by this...

I do this for compactness btw. Including code to deal with XDomainRequest to Webkit browsers is foolish, or including XHR2 code for IE is foolish, as they're never going to be able to run it. This is using Closure library, GWT uses a similar technique, as I understand it.

Sanjay

Devon H. O'Dell

unread,
Apr 2, 2012, 10:28:44 PM4/2/12
to Sanjay Menakuru, golan...@googlegroups.com, Andy Balholm, bugpowder, Vladimir Mihailenco, David Symonds
Op 2 april 2012 22:11 heeft Sanjay Menakuru <balas...@gmail.com> het
volgende geschreven:

> What are user agent strings for?

Identifying yourself as something.

> I compile different scripts per rendering engine, and one "general-purpose"
> one. If UA string is unlike any predefined patterns, I serve the general
> one. Further, the specific ones confirm that they are running on the right
> platform when they execute, and if not, they fallback to the general script.
>
> I've never seen any browsers "lie" about their user agent, what do you mean
> by this...

How would you ever possibly know? I have my browsers explicitly lie
about what UA they are so that I can log into a bank account that only
wants to allow IE. It is configurable, and people do configure it.

--dho

Sanjay Menakuru

unread,
Apr 2, 2012, 10:43:41 PM4/2/12
to golan...@googlegroups.com, Sanjay Menakuru, Andy Balholm, bugpowder, Vladimir Mihailenco, David Symonds
How would you ever possibly know?

Now that you mention it, I guess I wouldn't be able to tell. I thought you meant changing UA for http requests, but not changing it for javascript running in the browser.

I usually use it only for enhancements, like XHR2 to provide a progress bar for uploads. I'm pretty sure Closure uses it for removing unnecessary checks for window.ActiveXObject, and so forth. Or alternatively, to choose which layout to provide, ie mobile vs desktop (overridable by a cookie, of course).

Sanjay 

Devon H. O'Dell

unread,
Apr 2, 2012, 10:47:27 PM4/2/12
to Sanjay Menakuru, golan...@googlegroups.com, Andy Balholm, bugpowder, Vladimir Mihailenco, David Symonds
Op 2 april 2012 22:43 heeft Sanjay Menakuru <balas...@gmail.com> het
volgende geschreven:

>> How would you ever possibly know?
>
>
> Now that you mention it, I guess I wouldn't be able to tell. I thought you
> meant changing UA for http requests, but not changing it for javascript
> running in the browser.

I think we're talking about different things. I'm just talking about
the User-Agent header in the HTTP request. Javascript libraries will
always be able to tell what browser you're using based on what bugs
(errr, features) it implements on top of JS. In the case I provided,
the configuration is server-side and on the UA string.

markh...@google.com

unread,
Apr 17, 2012, 1:53:49 AM4/17/12
to golan...@googlegroups.com
Trying that, I get

panic: template: main.html:20: function "noescape" not defined

And I can't find noescape documented anywhere. Do I need to import something extra?

André Paquet

unread,
Apr 17, 2012, 9:08:08 AM4/17/12
to golan...@googlegroups.com
Look for "Typed Strings" in the html/template docs. Execute your template with the following instead of a string or a string struct member:

template.HTML("my already rendered html<br/>") 

I think it's the official way to prevent escaping. You can do similar for javascript and css.

Russ Cox

unread,
Feb 21, 2013, 4:54:21 PM2/21/13
to cameron...@cameroncurrie.net, golang-nuts
Reply all
Reply to author
Forward
0 new messages