stdlib: remove duplicate err check in New() and add XML escaping to user-controlled template values

Remove the dead second 'if err != nil' block after the already-checked
lib.Templates assignment.

Add html.EscapeString as 'xmlesc' template function and apply it to
user-controlled string parameters in ac:code, ac:status, and ac:box
templates. Values like .Title, .Color, .Language, and .Theme can contain
XML special characters (<, >, &, ") when supplied by users, which would
break Confluence storage format XML structure.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Manuel Rüger 2026-03-13 09:03:39 +01:00
parent 0d7caab5d8
commit 807d057f7b

View File

@ -1,6 +1,7 @@
package stdlib package stdlib
import ( import (
"html"
"strings" "strings"
"text/template" "text/template"
@ -25,10 +26,6 @@ func New(api *confluence.API) (*Lib, error) {
return nil, err return nil, err
} }
if err != nil {
return nil, err
}
return &lib, nil return &lib, nil
} }
@ -67,6 +64,9 @@ func templates(api *confluence.API) (*template.Template, error) {
"_", "_",
) )
}, },
"xmlesc": func(s string) string {
return html.EscapeString(s)
},
}, },
) )
@ -90,20 +90,20 @@ func templates(api *confluence.API) (*template.Template, error) {
// This template is used for rendering code in ``` // This template is used for rendering code in ```
`ac:code`: text( `ac:code`: text(
`<ac:structured-macro ac:name="code">`, `<ac:structured-macro ac:name="code">`,
/**/ `<ac:parameter ac:name="language">{{ .Language }}</ac:parameter>`, /**/ `<ac:parameter ac:name="language">{{ .Language | xmlesc }}</ac:parameter>`,
/**/ `<ac:parameter ac:name="collapse">{{ .Collapse }}</ac:parameter>`, /**/ `<ac:parameter ac:name="collapse">{{ .Collapse }}</ac:parameter>`,
/**/ `{{ if .Theme }}<ac:parameter ac:name="theme">{{ .Theme }}</ac:parameter>{{ end }}`, /**/ `{{ if .Theme }}<ac:parameter ac:name="theme">{{ .Theme | xmlesc }}</ac:parameter>{{ end }}`,
/**/ `{{ if .Linenumbers }}<ac:parameter ac:name="linenumbers">{{ .Linenumbers }}</ac:parameter>{{ end }}`, /**/ `{{ if .Linenumbers }}<ac:parameter ac:name="linenumbers">{{ .Linenumbers }}</ac:parameter>{{ end }}`,
/**/ `{{ if .Firstline }}<ac:parameter ac:name="firstline">{{ .Firstline }}</ac:parameter>{{ end }}`, /**/ `{{ if .Firstline }}<ac:parameter ac:name="firstline">{{ .Firstline }}</ac:parameter>{{ end }}`,
/**/ `{{ if .Title }}<ac:parameter ac:name="title">{{ .Title }}</ac:parameter>{{ end }}`, /**/ `{{ if .Title }}<ac:parameter ac:name="title">{{ .Title | xmlesc }}</ac:parameter>{{ end }}`,
/**/ `<ac:plain-text-body><![CDATA[{{ .Text | cdata }}]]></ac:plain-text-body>`, /**/ `<ac:plain-text-body><![CDATA[{{ .Text | cdata }}]]></ac:plain-text-body>`,
`</ac:structured-macro>`, `</ac:structured-macro>`,
), ),
`ac:status`: text( `ac:status`: text(
`<ac:structured-macro ac:name="status">`, `<ac:structured-macro ac:name="status">`,
`<ac:parameter ac:name="colour">{{ or .Color "Grey" }}</ac:parameter>`, `<ac:parameter ac:name="colour">{{ or .Color "Grey" | xmlesc }}</ac:parameter>`,
`<ac:parameter ac:name="title">{{ or .Title .Color }}</ac:parameter>`, `<ac:parameter ac:name="title">{{ or .Title .Color | xmlesc }}</ac:parameter>`,
`<ac:parameter ac:name="subtle">{{ or .Subtle false }}</ac:parameter>`, `<ac:parameter ac:name="subtle">{{ or .Subtle false }}</ac:parameter>`,
`</ac:structured-macro>`, `</ac:structured-macro>`,
), ),
@ -161,7 +161,7 @@ func templates(api *confluence.API) (*template.Template, error) {
`ac:box`: text( `ac:box`: text(
`<ac:structured-macro ac:name="{{ .Name }}">`, `<ac:structured-macro ac:name="{{ .Name }}">`,
`<ac:parameter ac:name="icon">{{ or .Icon "false" }}</ac:parameter>`, `<ac:parameter ac:name="icon">{{ or .Icon "false" }}</ac:parameter>`,
`{{ if .Title }}<ac:parameter ac:name="title">{{ .Title }}</ac:parameter>{{ end }}`, `{{ if .Title }}<ac:parameter ac:name="title">{{ .Title | xmlesc }}</ac:parameter>{{ end }}`,
`<ac:rich-text-body>{{ .Body }}</ac:rich-text-body>`, `<ac:rich-text-body>{{ .Body }}</ac:rich-text-body>`,
`</ac:structured-macro>`, `</ac:structured-macro>`,
), ),