diff --git a/sanitize.go b/sanitize.go index e203411..3b6d46e 100644 --- a/sanitize.go +++ b/sanitize.go @@ -537,7 +537,7 @@ func (p *Policy) sanitizeAttrs( tmpAttrs := []html.Attribute{} for _, htmlAttr := range cleanAttrs { switch elementName { - case "a", "area", "link": + case "a", "area", "base", "link": if htmlAttr.Key == "href" { if u, ok := p.validURL(htmlAttr.Val); ok { htmlAttr.Val = u @@ -546,7 +546,7 @@ func (p *Policy) sanitizeAttrs( break } tmpAttrs = append(tmpAttrs, htmlAttr) - case "blockquote", "q": + case "blockquote", "del", "ins", "q": if htmlAttr.Key == "cite" { if u, ok := p.validURL(htmlAttr.Val); ok { htmlAttr.Val = u @@ -555,7 +555,7 @@ func (p *Policy) sanitizeAttrs( break } tmpAttrs = append(tmpAttrs, htmlAttr) - case "img", "script": + case "audio", "embed", "iframe", "img", "script", "source", "track", "video": if htmlAttr.Key == "src" { if u, ok := p.validURL(htmlAttr.Val); ok { htmlAttr.Val = u @@ -580,7 +580,7 @@ func (p *Policy) sanitizeAttrs( // Add rel="nofollow" if a "href" exists switch elementName { - case "a", "area", "link": + case "a", "area", "base", "link": var hrefFound bool var externalLink bool for _, htmlAttr := range cleanAttrs { @@ -870,7 +870,6 @@ func (p *Policy) validURL(rawurl string) (string, bool) { urlPolicy, ok := p.allowURLSchemes[u.Scheme] if !ok { return "", false - } if urlPolicy == nil || urlPolicy(u) == true { @@ -894,7 +893,14 @@ func (p *Policy) validURL(rawurl string) (string, bool) { func linkable(elementName string) bool { switch elementName { - case "a", "area", "blockquote", "img", "link", "script": + case "a", "area", "base", "link": + // elements that allow .href + return true + case "blockquote", "del", "ins", "q": + // elements that allow .cite + return true + case "audio", "embed", "iframe", "img", "input", "script", "track", "video": + // elements that allow .src return true default: return false diff --git a/sanitize_test.go b/sanitize_test.go index 3033b37..eeeb199 100644 --- a/sanitize_test.go +++ b/sanitize_test.go @@ -431,6 +431,89 @@ func TestDataUri(t *testing.T) { } } +func TestGlobalURLPatternsViaCustomPolicy(t *testing.T) { + + p := UGCPolicy() + // youtube embeds + p.AllowElements("iframe") + p.AllowAttrs("width", "height", "frameborder").Matching(Integer).OnElements("iframe") + p.AllowAttrs("allow").Matching(regexp.MustCompile(`^(([\p{L}\p{N}_-]+)(; )?)+$`)).OnElements("iframe") + p.AllowAttrs("allowfullscreen").OnElements("iframe") + p.AllowAttrs("src").OnElements("iframe") + // These clobber... so you only get one and it applies to URLs everywhere + p.AllowURLSchemeWithCustomPolicy("mailto", func(url *url.URL) (allowUrl bool) { return false }) + p.AllowURLSchemeWithCustomPolicy("http", func(url *url.URL) (allowUrl bool) { return false }) + p.AllowURLSchemeWithCustomPolicy( + "https", + func(url *url.URL) bool { + // Allow YouTube + if url.Host == `www.youtube.com` { + return true + } + return false + }, + ) + + tests := []test{ + { + in: ``, + expected: ``, + }, + { + in: ``, + expected: ``, + }, + } + + for ii, test := range tests { + out := p.Sanitize(test.in) + if out != test.expected { + t.Errorf( + "test %d failed;\ninput : %s\noutput : %s\nexpected: %s", + ii, + test.in, + out, + test.expected, + ) + } + } +} + +func TestELementURLPatternsMatching(t *testing.T) { + + p := UGCPolicy() + // youtube embeds + p.AllowElements("iframe") + p.AllowAttrs("width", "height", "frameborder").Matching(Integer).OnElements("iframe") + p.AllowAttrs("allow").Matching(regexp.MustCompile(`^(([\p{L}\p{N}_-]+)(; )?)+$`)).OnElements("iframe") + p.AllowAttrs("allowfullscreen").OnElements("iframe") + p.AllowAttrs("src").Matching(regexp.MustCompile(`^https://www.youtube.com/.*$`)).OnElements("iframe") + + tests := []test{ + { + in: ``, + expected: ``, + }, + { + in: ``, + expected: ``, + }, + } + + for ii, test := range tests { + out := p.Sanitize(test.in) + if out != test.expected { + t.Errorf( + "test %d failed;\ninput : %s\noutput : %s\nexpected: %s", + ii, + test.in, + out, + test.expected, + ) + } + } +} + func TestAntiSamy(t *testing.T) { standardUrls := regexp.MustCompile(`(?i)^https?|mailto`)