sanitize both locator.URL and user.Picture
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -125,7 +126,8 @@ func (c *Comment) Sanitize() {
|
||||
c.Orig = p.Sanitize(c.Orig)
|
||||
c.User.ID = template.HTMLEscapeString(c.User.ID)
|
||||
c.User.Name = c.escapeHTMLWithSome(c.User.Name)
|
||||
c.User.Picture = p.Sanitize(c.User.Picture)
|
||||
c.User.Picture = c.sanitizeAsURL(c.User.Picture)
|
||||
c.Locator.URL = c.sanitizeAsURL(c.Locator.URL)
|
||||
}
|
||||
|
||||
// Snippet from comment's text
|
||||
@@ -149,6 +151,20 @@ func (c *Comment) Snippet(limit int) string {
|
||||
return string(snippet) + " ..."
|
||||
}
|
||||
|
||||
var reHref = regexp.MustCompile(`<a\s+(?:[^>]*?\s+)?href="([^"]*)"`)
|
||||
|
||||
// wrap with href to trigger bluemonday sanitizer
|
||||
// clean href after sanitizing done
|
||||
func (c *Comment) sanitizeAsURL(inp string) string {
|
||||
h := fmt.Sprintf(`<a href="%s">`, inp)
|
||||
clean := bluemonday.UGCPolicy().Sanitize(h)
|
||||
match := reHref.FindStringSubmatch(clean)
|
||||
if len(match) > 1 {
|
||||
return match[1]
|
||||
}
|
||||
return "" // this shouldn't happen as we build the href
|
||||
}
|
||||
|
||||
func (c *Comment) escapeHTMLWithSome(inp string) string {
|
||||
res := template.HTMLEscapeString(inp)
|
||||
res = strings.Replace(res, """, "\"", -1)
|
||||
|
||||
@@ -14,6 +14,7 @@ func TestComment_Sanitize(t *testing.T) {
|
||||
inp Comment
|
||||
out Comment
|
||||
}{
|
||||
|
||||
{inp: Comment{}, out: Comment{}},
|
||||
{
|
||||
inp: Comment{
|
||||
@@ -47,6 +48,25 @@ func TestComment_Sanitize(t *testing.T) {
|
||||
inp: Comment{Text: "blah & & 123", User: User{Name: "name <> & ' ` \""}},
|
||||
out: Comment{Text: `blah & & 123`, User: User{Name: "name <> & ' ` \""}},
|
||||
},
|
||||
|
||||
{
|
||||
inp: Comment{Text: "blah blah", Locator: Locator{URL: "javascript:alert('XSS1')"}},
|
||||
out: Comment{Text: "blah blah", Locator: Locator{URL: ""}},
|
||||
},
|
||||
{
|
||||
inp: Comment{Text: "blah blah", Locator: Locator{URL: "javascript:alert(document.domain)//"}},
|
||||
out: Comment{Text: "blah blah", Locator: Locator{URL: ""}},
|
||||
},
|
||||
{
|
||||
inp: Comment{Text: "blah blah", Locator: Locator{URL: "<script>alert()</script>"}},
|
||||
out: Comment{Text: "blah blah", Locator: Locator{URL: "%3Cscript%3Ealert%28%29%3C/script%3E"}},
|
||||
},
|
||||
{
|
||||
inp: Comment{Text: "blah blah",
|
||||
Locator: Locator{URL: "/p/2021/03/23/prep-747/#remark42__comment-1b365913-7056-4920-b9ad-01304bdda085"}},
|
||||
out: Comment{Text: "blah blah",
|
||||
Locator: Locator{URL: "/p/2021/03/23/prep-747/#remark42__comment-1b365913-7056-4920-b9ad-01304bdda085"}},
|
||||
},
|
||||
}
|
||||
|
||||
for n, tt := range tbl {
|
||||
@@ -159,3 +179,40 @@ func TestComment_Snippet(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestComment_sanitizeAsURL(t *testing.T) {
|
||||
|
||||
tbl := []struct {
|
||||
inp, out string
|
||||
}{
|
||||
{
|
||||
"/p/2021/03/23/prep-747/#remark42__comment-1b365913-7056-4920-b9ad-01304bdda085",
|
||||
"/p/2021/03/23/prep-747/#remark42__comment-1b365913-7056-4920-b9ad-01304bdda085",
|
||||
},
|
||||
{
|
||||
"https://radio-t.com/p/2021/03/23/prep-747/#remark42__comment-1b365913-7056-4920-b9ad-01304bdda085",
|
||||
"https://radio-t.com/p/2021/03/23/prep-747/#remark42__comment-1b365913-7056-4920-b9ad-01304bdda085",
|
||||
},
|
||||
{
|
||||
"javascript:alert(document.domain)//",
|
||||
"",
|
||||
},
|
||||
{
|
||||
"<script>alert()</script>",
|
||||
"%3Cscript%3Ealert%28%29%3C/script%3E",
|
||||
},
|
||||
{
|
||||
"<a href=javascript:alert(document.domain)//>xxx</a>",
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tbl {
|
||||
tt := tt
|
||||
c := Comment{}
|
||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||
assert.Equal(t, tt.out, c.sanitizeAsURL(tt.inp))
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user