html/template: rewriting html/template files #17933
Labels
FrozenDueToAge
NeedsDecision
Feedback is required from experts, contributors, and/or the community before a change can be made.
Milestone
This is with Go 1.7.
It would be nice if it was easier to rewrite
html/template
files but the current tools (html/template
andx/net/html
) seem to have a gap between them. Maybe there's a way to do this that I've missed, so let me explain the problems I wanted to solve in detail.I'm trying to make it easy to support CSP inline hashing in my templates without nagging users and requiring them to remember to use some custom funcs instead of the usual HTML. It'd also be nice to have form-based CSRF protection which would be implemented in a similar way. I'm sure there are other similar rewrites, but these security-focused ones were the first I've run into.
Both CSP inline hashing and form-based CSRF protection involve a developer adding additional attributes or elements to a template. In the CSP inline hashing case, it's an attribute or nonce added
script
tags. In form-based CSRF protection, it can be a hiddeninput
that sends up a per-request token inside aform
tag.It would be nice to be able to, at parse time, not execution time, pull apart a
html/template
template, inspect it for the relevant tags, and then change the template for the user instead of returning an error if they forgot the important elements. At parse time, the code has all the data it needs to adjust the template. Similar to whygofmt
is capable of rewriting a file, adjusting a template automatically instead of telling them they made an error would a much nicer experience for the developer.In the form-based CSRF case, the template rewrite would be adding a
input
tag that calls a template func (or struct value) that has the token data. In the CSP inline hashing case, the rewrite would be detecting if thescript
tag contained only static information and adding the hash automatically, or returning an error if the developer needs to get involved (usually, to handle the case of requesting javascript files from elsewhere on the web).However,
html/template
only hastext/template/parse
as its AST which doesn't suffice for working at the level of HTML semantics. Folks have offered upx/net/html
'sParseFragment
as a solution but that doesn't work well.One problem is that
x/net/html
'sParseFragment
makes it difficult to render exactly back what was in a template. Without providing a context*html.Node
, you'll get back a tree with additional bogus nodes added around the outside. This doesn't work well because rewriting code may need to behave differently depending on what context*html.Node
is in play instead of guessing that all templates are inbody
or whatever. But calculating that context*html.Node
is difficult since a template can be loaded from other templates. That would involve writing similar template loading code to what is already insidetext/template
.A second problem since some of those templates will be called in different escaping contexts, folks using
ParseFragment
have to re-do the escape context code inhtml/template
withinx/net/html
's AST.I haven't found a way to make my templates better without requiring the developer to handle more of what would otherwise be easily automated problems.
I'm not sure, yet, what kind of work it would take to make html/template easier for this purpose. Maybe if
html.Node
gained line and column information someone could compare it totext/template/parse.Pos
and do some grungy work to get the right contextNode
s?Maybe other folks have clearer ideas.
The text was updated successfully, but these errors were encountered: