diff --git a/backend/app/store/comment.go b/backend/app/store/comment.go index b5221494..a38c2c5f 100644 --- a/backend/app/store/comment.go +++ b/backend/app/store/comment.go @@ -127,10 +127,10 @@ func (c *Comment) Sanitize() { c.Text = p.Sanitize(c.Text) c.Orig = p.Sanitize(c.Orig) c.User.ID = template.HTMLEscapeString(c.User.ID) - c.User.Name = c.escapeHTMLWithSome(c.User.Name) + c.User.Name = c.SanitizeText(c.User.Name) c.User.Picture = c.SanitizeAsURL(c.User.Picture) c.Locator.URL = c.SanitizeAsURL(c.Locator.URL) - c.PostTitle = p.Sanitize(c.PostTitle) + c.PostTitle = c.SanitizeText(c.PostTitle) } // Snippet from comment's text @@ -169,13 +169,14 @@ func (c *Comment) SanitizeAsURL(inp string) string { func (c *Comment) escapeHTMLWithSome(inp string) string { res := template.HTMLEscapeString(inp) + res = strings.Replace(res, "&", "&", -1) res = strings.Replace(res, """, "\"", -1) res = strings.Replace(res, "'", "'", -1) - res = strings.Replace(res, "&", "&", -1) return res } // SanitizeText used to sanitize any input string func (c *Comment) SanitizeText(inp string) string { - return c.escapeHTMLWithSome(bluemonday.UGCPolicy().Sanitize(inp)) + clean := bluemonday.UGCPolicy().Sanitize(inp) + return c.escapeHTMLWithSome(clean) } diff --git a/backend/app/store/comment_test.go b/backend/app/store/comment_test.go index 205cc3fa..03a77899 100644 --- a/backend/app/store/comment_test.go +++ b/backend/app/store/comment_test.go @@ -35,6 +35,10 @@ func TestComment_Sanitize(t *testing.T) { User: User{ID: "id", Name: "xyz-123"}, }, }, + { + inp: Comment{Text: "blah `123`"}, + out: Comment{Text: "blah `123`"}, + }, { inp: Comment{Text: "blah & & 123 — —"}, out: Comment{Text: `blah & & 123 — —`}, @@ -43,9 +47,17 @@ func TestComment_Sanitize(t *testing.T) { inp: Comment{Text: "blah & & 123 — —"}, out: Comment{Text: `blah & & 123 — —`}, }, + { + inp: Comment{Text: "blah `123`", User: User{Name: "name \"xxx\" `yyy`"}}, + out: Comment{Text: "blah `123`", User: User{Name: "name \"xxx\" `yyy`"}}, + }, { inp: Comment{Text: "blah & & 123", User: User{Name: "name <> & ' ` \""}}, - out: Comment{Text: `blah & & 123`, User: User{Name: "name <> & ' ` \""}}, + out: Comment{Text: `blah & & 123`, User: User{Name: "name <> & ' ` \""}}, + }, + { + inp: Comment{Text: "blah & & 123", User: User{Name: `name XSS`}}, + out: Comment{Text: `blah & & 123`, User: User{Name: "name XSS"}}, }, { @@ -79,8 +91,10 @@ func TestComment_Sanitize(t *testing.T) { } for n, tt := range tbl { - tt.inp.Sanitize() - assert.Equal(t, tt.out, tt.inp, "check #%d", n) + t.Run(strconv.Itoa(n), func(t *testing.T) { + tt.inp.Sanitize() + assert.Equal(t, tt.out, tt.inp, "check #%d", n) + }) } } diff --git a/backend/app/store/service/service_test.go b/backend/app/store/service/service_test.go index a7dd6e62..5974a30a 100644 --- a/backend/app/store/service/service_test.go +++ b/backend/app/store/service/service_test.go @@ -97,6 +97,36 @@ func TestService_CreateFromPartial(t *testing.T) { assert.Equal(t, comment.Votes, res.Votes) } +func TestService_CreateWithQuotesInTitle(t *testing.T) { + ks := admin.NewStaticKeyStore("secret 123") + eng, teardown := prepStoreEngine(t) + defer teardown() + b := DataStore{Engine: eng, AdminStore: ks} + comment := store.Comment{ + Text: "text", + PostTitle: "some example \"in quotes\"", + Timestamp: time.Date(2018, 3, 25, 16, 34, 33, 0, time.UTC), + Votes: map[string]bool{"u1": true, "u2": false}, + VotedIPs: map[string]store.VotedIPInfo{"xxx": {Value: true, Timestamp: time.Now()}, + "yyy": {Value: false, Timestamp: time.Now()}}, + User: store.User{IP: "192.168.1.1", ID: "user", Name: "name"}, + Locator: store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, + } + id, err := b.Create(comment) + assert.NoError(t, err) + assert.True(t, id != "", id) + + res, err := b.Engine.Get(getReq(store.Locator{URL: "https://radio-t.com", SiteID: "radio-t"}, id)) + assert.NoError(t, err) + t.Logf("%+v", res) + assert.Equal(t, "text", res.Text) + assert.Equal(t, comment.Timestamp, res.Timestamp) + assert.Equal(t, "user", res.User.ID) + assert.Equal(t, "name", res.User.Name) + assert.Equal(t, "23f97cf4d5c29ef788ca2bdd1c9e75656c0e4149", res.User.IP) + assert.Equal(t, "some example \"in quotes\"", res.PostTitle) +} + func TestService_CreateFromPartialWithTitle(t *testing.T) { ks := admin.NewStaticKeyStore("secret 123") eng, teardown := prepStoreEngine(t)