Documentation ¶
Overview ¶
Package woof provides serialization of Go values to be used in HTML documents.
As such, it also provides escaping and filter mechanisms closely related to the filters and escapers of Go's stdlib package html/template.
Terminology ¶
A FILTER is a function that is given untrusted data for a specific content type.
If the function deems the data safe, it returns it as is.
If the data is deemed unsafe, the filter will replace the data or some of its parts with a safe replacement or delete unsafe parts, CHANGING OR FULLY REPLACING THE DATA to ensure safety.
An ESCAPER is a function that is given untrusted data for a specific content type and replaces unsafe parts with escape sequences, so that the data can be used in its content domain without unintended side effects.
Index ¶
- Constants
- Variables
- func CanIndex(val any, i any) bool
- func IsZero(t any) bool
- func Must[T ~string](ctx *Context, f func(val any) (T, error), val any) string
- func MustContext[T ~string](ctx *Context, f func(vals ...any) (T, error), vals ...any) string
- func Ptr[T any](t T) *T
- func ResolveDefault[T any](val *T, defaultVal T) T
- func Stringify(val any) (string, error)
- func Ternary[T any](cond bool, ifTrue, ifFalse T) T
- func WriteAny[T ~string](ctx *Context, escaper func(val any) (T, error), val any)
- func WriteAnys[T ~string](ctx *Context, escaper func(vals ...any) (T, error), vals ...any)
- func WriteAttr[T ~string](ctx *Context, name string, val any, escaper func(val any) (T, error))
- type CSS
- type ContentType
- type Context
- func (ctx *Context) BufferClass(class any)
- func (ctx *Context) BufferClassAttr(class HTMLAttrVal)
- func (ctx *Context) CloseStartTag(extraClasses HTMLAttrVal, void bool)
- func (ctx *Context) Closed()
- func (ctx *Context) InjectNonce()
- func (ctx *Context) Panic(err error)
- func (ctx *Context) Recover() error
- func (ctx *Context) SetScriptNonce(nonce any)
- func (ctx *Context) Unclosed()
- func (ctx *Context) Write(s string)
- func (ctx *Context) WriteBytes(data []byte)
- type HTMLAttrVal
- type HTMLBody
- type HTMLText
- type JS
- type JSAttrVal
- type JSStr
- type MapEntry
- type MapSlice
- type Ordered
- type Srcset
- type URL
- type UnprintableValueError
Constants ¶
const UnsafeReplacement = "ZcorgiZ"
Variables ¶
var AttrTypes = map[string]ContentType{ "accept": ContentTypePlain, "action": ContentTypeURL, "alt": ContentTypePlain, "archive": ContentTypeURL, "autocomplete": ContentTypePlain, "autofocus": ContentTypePlain, "autoplay": ContentTypePlain, "background": ContentTypeURL, "border": ContentTypePlain, "checked": ContentTypePlain, "cite": ContentTypeURL, "class": ContentTypePlain, "classid": ContentTypeURL, "codebase": ContentTypeURL, "cols": ContentTypePlain, "colspan": ContentTypePlain, "contenteditable": ContentTypePlain, "contextmenu": ContentTypePlain, "controls": ContentTypePlain, "coords": ContentTypePlain, "data": ContentTypeURL, "datetime": ContentTypePlain, "default": ContentTypePlain, "dir": ContentTypePlain, "dirname": ContentTypePlain, "disabled": ContentTypePlain, "draggable": ContentTypePlain, "dropzone": ContentTypePlain, "for": ContentTypePlain, "formaction": ContentTypeURL, "formtarget": ContentTypePlain, "headers": ContentTypePlain, "height": ContentTypePlain, "hidden": ContentTypePlain, "high": ContentTypePlain, "href": ContentTypeURL, "hreflang": ContentTypePlain, "icon": ContentTypeURL, "id": ContentTypePlain, "ismap": ContentTypePlain, "kind": ContentTypePlain, "label": ContentTypePlain, "lang": ContentTypePlain, "list": ContentTypePlain, "longdesc": ContentTypeURL, "loop": ContentTypePlain, "low": ContentTypePlain, "manifest": ContentTypeURL, "max": ContentTypePlain, "maxlength": ContentTypePlain, "media": ContentTypePlain, "mediagroup": ContentTypePlain, "min": ContentTypePlain, "multiple": ContentTypePlain, "name": ContentTypePlain, "open": ContentTypePlain, "optimum": ContentTypePlain, "placeholder": ContentTypePlain, "poster": ContentTypeURL, "profile": ContentTypeURL, "preload": ContentTypePlain, "pubdate": ContentTypePlain, "radiogroup": ContentTypePlain, "readonly": ContentTypePlain, "required": ContentTypePlain, "reversed": ContentTypePlain, "rows": ContentTypePlain, "rowspan": ContentTypePlain, "spellcheck": ContentTypePlain, "scope": ContentTypePlain, "scoped": ContentTypePlain, "seamless": ContentTypePlain, "selected": ContentTypePlain, "shape": ContentTypePlain, "size": ContentTypePlain, "sizes": ContentTypePlain, "span": ContentTypePlain, "src": ContentTypeURL, "srcdoc": ContentTypeHTML, "srclang": ContentTypePlain, "srcset": ContentTypeSrcset, "start": ContentTypePlain, "step": ContentTypePlain, "style": ContentTypeCSS, "tabindex": ContentTypePlain, "target": ContentTypePlain, "title": ContentTypePlain, "usemap": ContentTypeURL, "width": ContentTypePlain, "wrap": ContentTypePlain, "xmlns": ContentTypeURL, }
AttrTypes describes the value of the given attribute. If an attribute affects (or can mask) the encoding or interpretation of other content, or affects the contents, idempotency, or credentials of a network message, then the value in this map is ContentTypeUnsafe. This map is derived from HTML5, specifically https://www.w3.org/TR/html5/Overview.html#attributes-1 as well as "%URI"-typed attributes from https://www.w3.org/TR/html4/index/attributes.html
Functions ¶
func MustContext ¶
func ResolveDefault ¶
func ResolveDefault[T any](val *T, defaultVal T) T
func Stringify ¶
Stringify converts the passed value to a string.
It accepts values of type string, all ints, uints and floats, and fmt.Stringer. val may also be a pointer to any of the above types, or a type approximation, i.e. satisfy interface{ ~string }, interface{ ~int }, etc.
If val is nil or dereferences to nil, Stringify returns "".
If Stringify can't print a value, i.e. val is of an unsupported type, Stringify returns a pointer to an UnprintableValueError.
func WriteAttr ¶
WriteAttr is a utility for writing attributes, that correctly handles bool values.
If val is a bool and true, WriteAttr writes a space followed by name.
If val is a bool and false, WriteAttr writes nothing.
In any other case, WriteAttr writes a space, followed by the name, '="', and then the escaped attributes.
Types ¶
type CSS ¶
type CSS string
CSS encapsulates known safe content that matches any of:
- The CSS3 stylesheet production, such as `p { color: purple }`.
- The CSS3 rule production, such as `a[href=~"https:"].foo#bar`.
- CSS3 declaration productions, such as `color: red; margin: 2px`.
- The CSS3 value production, such as `rgba(0, 0, 255, 127)`.
See https://www.w3.org/TR/css3-syntax/#parsing and https://web.archive.org/web/20090211114933/http://w3.org/TR/css3-syntax#style
Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output.
func EscapeCSSValue ¶
EscapeCSSValue escapes HTML and CSS special characters using \<hex>+ escapes.
The output is safe to use in HTML bodies and (possibly quote-wrapped) attributes without further HTML escaping.
func FilterCSSValue ¶
FilterCSSValue allows innocuous CSS values in the output including CSS quantities (10px or 25%), ID or class literals (#foo, .bar), keyword values (inherit, blue), and colors (#888). It filters out unsafe values, such as those that affect token boundaries, and anything that might execute scripts.
type ContentType ¶
type ContentType uint8
const ( ContentTypePlain ContentType = iota ContentTypeCSS ContentTypeHTML ContentTypeJS ContentTypeURL ContentTypeSrcset )
func AttrType ¶
func AttrType(name string) ContentType
AttrType returns a conservative (upper-bound on authority) guess at the type of the lowercase named attribute.
func (ContentType) String ¶
func (t ContentType) String() string
type Context ¶
type Context struct {
// contains filtered or unexported fields
}
func NewContext ¶
func (*Context) BufferClass ¶
func (*Context) BufferClassAttr ¶
func (ctx *Context) BufferClassAttr(class HTMLAttrVal)
func (*Context) CloseStartTag ¶
func (ctx *Context) CloseStartTag(extraClasses HTMLAttrVal, void bool)
CloseStartTag writes the buffered classes, if any, plus, optionally, the passed pre-escaped extra classes and closes the start tag.
If the tag has already been closed, CloseStartTag is a no-op.
func (*Context) Closed ¶
func (ctx *Context) Closed()
Closed signals that an element tag has been closed.
func (*Context) InjectNonce ¶
func (ctx *Context) InjectNonce()
func (*Context) SetScriptNonce ¶
func (*Context) Unclosed ¶
func (ctx *Context) Unclosed()
Unclosed signals that an element tag has been opened but not yet closed.
func (*Context) WriteBytes ¶
type HTMLAttrVal ¶
type HTMLAttrVal string
HTMLAttrVal represents a known safe HTML attribute value fragment that can be placed between double-quotes to be used as part of an HTML attribute.
It must at least escape ["&].
Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output.
func EscapeHTMLAttrVal ¶
func EscapeHTMLAttrVal(val any) (HTMLAttrVal, error)
EscapeHTMLAttrVal escapes s by replacing [&"] so that it can safely be placed between double quotes as an attribute value.
It does not perform further context specific escaping.
type HTMLBody ¶
type HTMLBody string
HTMLBody represents a known safe n HTML fragment to be placed in the body of an element or the root of the document.
It should not be used for HTML from a third-party, or HTML with unclosed tags or comments and must escape at least [<&].
Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output.
func EscapeHTMLBody ¶
EscapeHTMLBody replaces [&<] with escape sequences.
It should only be used to escape a tag body's content.
Since '>' is not escaped, previous start or end tags must be closed using a '>' to not cause unexpected side effects. This is the case for all escaped code generated by corgi and could only be a problem if user manually writes unclosed tags using unescaped assigns, which is discouraged by the corgi documentation.
type HTMLText ¶
type HTMLText string
HTMLText represents an HTML fragment consisting purely of escaped text suitable to be placed both in the body of a tag (or the root of the document), and as an attribute value, possibly later enclosed in quotes.
This effectively makes HTMLText a mixture of HTMLBody and HTMLAttrVal.
As such, it must not contain any elements and must escape ["<&].
Corgi only considers HTMLText safe for "plain" attributes and won't, for example, allow the usage of a HTMLText, as an href.
Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output.
func EscapeHTML ¶
EscapeHTML replaces [&'<>"] with escape sequences.
Usually, EscapeHTMLBody and [EscapeAttrVal] are more appropriate, as they have a smaller set of replacements, specific to their context.
This does not mean however, that content escaped with EscapeHTML, is not valid in HTML bodies or attributes (the opposite is true). Instead, EscapeHTML simply escapes more characters than required by those contexts.
type JS ¶
type JS string
JS encapsulates a known safe EcmaScript5 Expression, for example, `(x + y * z())`. Template authors are responsible for ensuring that typed expressions do not break the intended precedence and that there is no statement/expression ambiguity as when passing an expression like "{ foo: bar() }\n['foo']()", which is both a valid Expression and a valid Program with a very different meaning.
Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output.
Using JS to include valid but untrusted JSON is not safe. A safe alternative is to parse the JSON with json.Unmarshal and then pass the resultant object into the template, where it will be converted to sanitized JSON when presented in a JavaScript context.
type JSAttrVal ¶
type JSAttrVal string
JSAttrVal is a js attribute safe to be embedded in double quotes and used as an attribute value.
Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output.
Using JS to include valid but untrusted JSON is not safe. A safe alternative is to parse the JSON with json.Unmarshal and then pass the resultant object into the template, where it will be converted to sanitized JSON when presented in a JavaScript context.
func EscapeJSAttrVal ¶
type JSStr ¶
type JSStr string
JSStr encapsulates a sequence of characters meant to be embedded between quotes in a JavaScript expression. The string must match a series of StringCharacters:
StringCharacter :: SourceCharacter but not `\` or LineTerminator | EscapeSequence
Note that LineContinuations are not allowed. JSStr("foo\\nbar") is fine, but JSStr("foo\\\nbar") is not.
Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will be included verbatim in the template output.
type MapSlice ¶
func OrderedMap ¶
type Srcset ¶
type Srcset string
Srcset represents a known safe srcset attribute value, safe to be embedded between two double quotes and used as a srcset attribute or part of a srcset attribute.
Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will only be HTML escaped before including in template output.
func FilterSrcset ¶
type URL ¶
type URL string
URL represents a known safe URL or URL fragment.
Use of this type presents a security risk: the encapsulated content should come from a trusted source, as it will only be HTML escaped before including in template output.
func NormalizeURL ¶
type UnprintableValueError ¶
type UnprintableValueError struct {
Val any
}
func (*UnprintableValueError) Error ¶
func (err *UnprintableValueError) Error() string