mirror of
https://github.com/gohugoio/hugo.git
synced 2026-08-24 23:38:53 +00:00
Fix potential content XSS by escaping dangerous URLs in links and images
* This issue in question was fixed upstream in https://github.com/yuin/goldmark/releases/tag/v1.8.2 * We do, however, have a copy of the affected functions, used as fallbacks when no render hook are defined for e.g. links and images, so we need to port these fixes to our copy of the affected functions.
This commit is contained in:
@@ -1035,3 +1035,33 @@ foo[^1] and bar[^2]
|
||||
"<p>foo<sup id=\"hb5cdcabc9e678612fnref:1\"><a href=\"#hb5cdcabc9e678612fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup> and bar<sup id=\"hb5cdcabc9e678612fnref:2\"><a href=\"#hb5cdcabc9e678612fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2</a></sup></p>\n<div class=\"footnotes\" role=\"doc-endnotes\">\n<hr>\n<ol>\n<li id=\"hb5cdcabc9e678612fn:1\">\n<p>footnote one <a href=\"#hb5cdcabc9e678612fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">back</a></p>\n</li>\n<li id=\"hb5cdcabc9e678612fn:2\">\n<p>footnote two <a href=\"#hb5cdcabc9e678612fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\">back</a></p>\n</li>\n</ol>\n</div>",
|
||||
)
|
||||
}
|
||||
|
||||
func TestRenderLinkDefaultDangerous(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
/*
|
||||
Content: <p>Link: <a href="javascript:alert(1)">Click me</a>
|
||||
AutoLink: <a href="">javascript:alert(1)</a>
|
||||
Image: <img src="javascript:alert(1)" alt="alt"></p>
|
||||
*/
|
||||
|
||||
files := `
|
||||
-- content/p1.md --
|
||||
---
|
||||
title: "p1"
|
||||
---
|
||||
Link: [Click me](javascript:alert(1))
|
||||
AutoLink: <javascript:alert(2)>
|
||||
Image: )
|
||||
-- layouts/all.html --
|
||||
Content: {{ .Content }}
|
||||
`
|
||||
|
||||
b := hugolib.Test(t, files)
|
||||
|
||||
b.AssertFileContent("public/p1/index.html",
|
||||
`! alert(1)"`,
|
||||
`! href="javascript:alert(2)"`,
|
||||
`! alert(3)"`,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -230,8 +230,9 @@ func (r *hookedRenderer) renderImageDefault(w util.BufWriter, source []byte, nod
|
||||
}
|
||||
n := node.(*ast.Image)
|
||||
_, _ = w.WriteString("<img src=\"")
|
||||
if r.Unsafe || !html.IsDangerousURL(n.Destination) {
|
||||
_, _ = w.Write(util.EscapeHTML(util.URLEscape(n.Destination, true)))
|
||||
dest := util.URLEscape(n.Destination, true)
|
||||
if r.Unsafe || !html.IsDangerousURL(dest) {
|
||||
_, _ = w.Write(util.EscapeHTML(dest))
|
||||
}
|
||||
_, _ = w.WriteString(`" alt="`)
|
||||
r.renderTexts(w, source, n)
|
||||
@@ -375,8 +376,9 @@ func (r *hookedRenderer) renderLinkDefault(w util.BufWriter, source []byte, node
|
||||
n := node.(*ast.Link)
|
||||
if entering {
|
||||
_, _ = w.WriteString("<a href=\"")
|
||||
if r.Unsafe || !html.IsDangerousURL(n.Destination) {
|
||||
_, _ = w.Write(util.EscapeHTML(util.URLEscape(n.Destination, true)))
|
||||
dest := util.URLEscape(n.Destination, true)
|
||||
if r.Unsafe || !html.IsDangerousURL(dest) {
|
||||
_, _ = w.Write(util.EscapeHTML(util.EscapeHTML(dest)))
|
||||
}
|
||||
_ = w.WriteByte('"')
|
||||
if n.Title != nil {
|
||||
@@ -445,12 +447,15 @@ func (r *hookedRenderer) renderAutoLinkDefault(w util.BufWriter, source []byte,
|
||||
}
|
||||
|
||||
_, _ = w.WriteString(`<a href="`)
|
||||
url := r.autoLinkURL(n, source)
|
||||
url := util.URLEscape(r.autoLinkURL(n, source), false)
|
||||
|
||||
label := n.Label(source)
|
||||
if n.AutoLinkType == ast.AutoLinkEmail && !bytes.HasPrefix(bytes.ToLower(url), []byte("mailto:")) {
|
||||
_, _ = w.WriteString("mailto:")
|
||||
}
|
||||
_, _ = w.Write(util.EscapeHTML(util.URLEscape(url, false)))
|
||||
if r.Unsafe || !html.IsDangerousURL(url) {
|
||||
_, _ = w.Write(util.EscapeHTML(url))
|
||||
}
|
||||
if n.Attributes() != nil {
|
||||
_ = w.WriteByte('"')
|
||||
html.RenderAttributes(w, n, html.LinkAttributeFilter)
|
||||
|
||||
Reference in New Issue
Block a user