feat(backend): comment reply text xss fix (#761)
* feat(backend): comment reply text xss fix * fix(root): pre-commit npx to yarn * chore(server): added test
This commit is contained in:
committed by
GitHub
parent
ff0836275c
commit
e5880e73f2
+1
-1
@@ -3,4 +3,4 @@
|
||||
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged
|
||||
yarn lint-staged
|
||||
|
||||
@@ -13,7 +13,8 @@ const {
|
||||
viewComment,
|
||||
archiveComment,
|
||||
editComment,
|
||||
streamResourceCheck
|
||||
streamResourceCheck,
|
||||
formatCommentText
|
||||
} = require('@/modules/comments/services')
|
||||
|
||||
const authorizeStreamAccess = async ({ streamId, userId, auth }) => {
|
||||
@@ -60,6 +61,9 @@ module.exports = {
|
||||
limit: args.limit,
|
||||
cursor: args.cursor
|
||||
})
|
||||
},
|
||||
text(parent) {
|
||||
return formatCommentText(parent)
|
||||
}
|
||||
},
|
||||
Stream: {
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
'use strict'
|
||||
const crs = require('crypto-random-string')
|
||||
const knex = require('@/db/knex')
|
||||
const sanitizeHtml = require('sanitize-html')
|
||||
|
||||
const Comments = () => knex('comments')
|
||||
const CommentLinks = () => knex('comment_links')
|
||||
const CommentViews = () => knex('comment_views')
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Format comment text field (e.g. for returning to frontend or saving to DB)
|
||||
* @param {Object} comment
|
||||
* @returns {string}
|
||||
*/
|
||||
formatCommentText(comment) {
|
||||
if (!comment || !comment.text) return ''
|
||||
return sanitizeHtml(comment.text)
|
||||
},
|
||||
async streamResourceCheck({ streamId, resources }) {
|
||||
// this itches - a for loop with queries... but okay let's hit the road now
|
||||
for (const res of resources) {
|
||||
@@ -74,6 +84,7 @@ module.exports = {
|
||||
|
||||
comment.id = crs({ length: 10 })
|
||||
comment.authorId = userId
|
||||
comment.text = module.exports.formatCommentText(comment)
|
||||
|
||||
await Comments().insert(comment)
|
||||
try {
|
||||
@@ -105,6 +116,8 @@ module.exports = {
|
||||
streamId,
|
||||
parentComment: parentCommentId
|
||||
}
|
||||
comment.text = module.exports.formatCommentText(comment)
|
||||
|
||||
await Comments().insert(comment)
|
||||
try {
|
||||
const commentLink = { resourceId: parentCommentId, resourceType: 'comment' }
|
||||
|
||||
@@ -78,6 +78,22 @@ describe('Comments @comments', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('Should not accept complex HTML in the comment text', async () => {
|
||||
const commentId = await createComment({
|
||||
userId: user.id,
|
||||
input: {
|
||||
streamId: stream.id,
|
||||
resources: [{ resourceId: stream.id, resourceType: 'stream' }],
|
||||
text: 'Some <img src/onerror=alert(1)> <strong>epic</strong> <a href="javascript:alert(1)">cool</a> text!',
|
||||
data: { justSome: crs({ length: 10 }) }
|
||||
}
|
||||
})
|
||||
|
||||
const comment = await getComment({ id: commentId })
|
||||
expect(comment).to.be.ok
|
||||
expect((comment.text.match(/alert/) || []).length).to.equal(0)
|
||||
})
|
||||
|
||||
it('Should not be allowed to comment without specifying at least one target resource', async () => {
|
||||
await createComment({
|
||||
userId: user.id,
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
"prom-client": "^14.0.1",
|
||||
"redis": "^3.1.1",
|
||||
"response-time": "^2.3.2",
|
||||
"sanitize-html": "^2.4.0",
|
||||
"sanitize-html": "^2.7.0",
|
||||
"sharp": "^0.29.3",
|
||||
"string-pixel-width": "^1.10.0",
|
||||
"subscriptions-transport-ws": "0.9.0",
|
||||
|
||||
@@ -3047,7 +3047,7 @@ __metadata:
|
||||
prom-client: ^14.0.1
|
||||
redis: ^3.1.1
|
||||
response-time: ^2.3.2
|
||||
sanitize-html: ^2.4.0
|
||||
sanitize-html: ^2.7.0
|
||||
sharp: ^0.29.3
|
||||
string-pixel-width: ^1.10.0
|
||||
subscriptions-transport-ws: 0.9.0
|
||||
@@ -20645,7 +20645,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"sanitize-html@npm:^2.4.0":
|
||||
"sanitize-html@npm:^2.7.0":
|
||||
version: 2.7.0
|
||||
resolution: "sanitize-html@npm:2.7.0"
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user