VYPR
Medium severity6.1NVD Advisory· Published Apr 15, 2026· Updated Apr 23, 2026

CVE-2026-5160

CVE-2026-5160

Description

Versions of the package github.com/yuin/goldmark/renderer/html before 1.7.17 are vulnerable to Cross-site Scripting (XSS) due to improper ordering of URL validation and normalization. The renderer validates link destinations using a prefix-based check (IsDangerousURL) before resolving HTML entities. This allows an attacker to bypass protocol filtering by encoding dangerous schemes using HTML5 named character references. For example, a payload such as javascript:alert(1) is not recognized as dangerous during validation, leading to arbitrary script execution in the context of applications that render the URL.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/yuin/goldmark/renderer/htmlGo
< 1.7.171.7.17

Affected products

1
  • cpe:2.3:a:yuin:goldmark:*:*:*:*:*:*:*:*
    Range: <1.7.17

Patches

1
cb46bbc4eca2

fix: prevent XSS by escaping dangerous URLs in links and images

https://github.com/yuin/goldmarkyuinMar 19, 2026via ghsa
2 files changed · +44 6
  • extra_test.go+34 0 modified
    @@ -245,3 +245,37 @@ func TestNestedATXHeadingAttributes(t *testing.T) {
     	}
     
     }
    +
    +func TestDangerousURLWithReferences(t *testing.T) {
    +	markdown := New(WithParserOptions(
    +		parser.WithAutoHeadingID(),
    +		parser.WithAttribute(),
    +	))
    +
    +	source := []byte(`[click](&#106;avascript:alert(1))`)
    +	expected := []byte(`<p><a href="">click</a></p>
    +`)
    +	var b bytes.Buffer
    +	_ = markdown.Convert(source, &b)
    +	if !bytes.Equal(expected, b.Bytes()) {
    +		t.Error("Dangerous URL with references should not be rendered:\n" + string(testutil.DiffPretty(expected, b.Bytes())))
    +	}
    +
    +	source = []byte(`<javascript:alert(document.domain)>`)
    +	expected = []byte(`<p><a href="">javascript:alert(document.domain)</a></p>
    +`)
    +	b.Reset()
    +	_ = markdown.Convert(source, &b)
    +	if !bytes.Equal(expected, b.Bytes()) {
    +		t.Error("Dangerous autolink should not be rendered:\n" + string(testutil.DiffPretty(expected, b.Bytes())))
    +	}
    +
    +	source = []byte(`![alt](javascript:alert(document.domain))`)
    +	expected = []byte(`<p><img src="" alt="alt"></p>
    +`)
    +	b.Reset()
    +	_ = markdown.Convert(source, &b)
    +	if !bytes.Equal(expected, b.Bytes()) {
    +		t.Error("Dangerous image should not be rendered:\n" + string(testutil.DiffPretty(expected, b.Bytes())))
    +	}
    +}
    
  • renderer/html/html.go+10 6 modified
    @@ -506,12 +506,14 @@ func (r *Renderer) renderAutoLink(
     		return ast.WalkContinue, nil
     	}
     	_, _ = w.WriteString(`<a href="`)
    -	url := n.URL(source)
    +	url := util.URLEscape(n.URL(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 || !IsDangerousURL(url) {
    +		_, _ = w.Write(util.EscapeHTML(url))
    +	}
     	if n.Attributes() != nil {
     		_ = w.WriteByte('"')
     		RenderAttributes(w, n, LinkAttributeFilter)
    @@ -581,8 +583,9 @@ func (r *Renderer) renderLink(w util.BufWriter, source []byte, node ast.Node, en
     	n := node.(*ast.Link)
     	if entering {
     		_, _ = w.WriteString("<a href=\"")
    -		if r.Unsafe || !IsDangerousURL(n.Destination) {
    -			_, _ = w.Write(util.EscapeHTML(util.URLEscape(n.Destination, true)))
    +		dest := util.URLEscape(n.Destination, true)
    +		if r.Unsafe || !IsDangerousURL(dest) {
    +			_, _ = w.Write(util.EscapeHTML(dest))
     		}
     		_ = w.WriteByte('"')
     		if n.Title != nil {
    @@ -609,8 +612,9 @@ func (r *Renderer) renderImage(w util.BufWriter, source []byte, node ast.Node, e
     	}
     	n := node.(*ast.Image)
     	_, _ = w.WriteString("<img src=\"")
    -	if r.Unsafe || !IsDangerousURL(n.Destination) {
    -		_, _ = w.Write(util.EscapeHTML(util.URLEscape(n.Destination, true)))
    +	dest := util.URLEscape(n.Destination, true)
    +	if r.Unsafe || !IsDangerousURL(dest) {
    +		_, _ = w.Write(util.EscapeHTML(dest))
     	}
     	_, _ = w.WriteString(`" alt="`)
     	r.renderTexts(w, source, n)
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.