From 61ca931e66c85111f10cf4ea6754d1e6bba4496e Mon Sep 17 00:00:00 2001 From: Matteo Pagliazzi Date: Tue, 28 Apr 2020 16:47:52 +0200 Subject: [PATCH] fix(string utils): do not escape possible regular expressions --- test/api/unit/libs/stringUtils.test.js | 12 ++++++++++++ test/api/v3/integration/chat/POST-chat.test.js | 8 -------- website/server/libs/stringUtils.js | 9 +++------ website/server/libs/user/validation.js | 6 +----- 4 files changed, 16 insertions(+), 19 deletions(-) create mode 100644 test/api/unit/libs/stringUtils.test.js diff --git a/test/api/unit/libs/stringUtils.test.js b/test/api/unit/libs/stringUtils.test.js new file mode 100644 index 0000000000..7183ecaecd --- /dev/null +++ b/test/api/unit/libs/stringUtils.test.js @@ -0,0 +1,12 @@ +import { getMatchesByWordArray } from '../../../../website/server/libs/stringUtils'; +import bannedWords from '../../../../website/server/libs/bannedWords'; + +describe('stringUtils', () => { + describe('getMatchesByWordArray', () => { + it('check all banned words are matched', async () => { + const message = bannedWords.join(','); + const matches = getMatchesByWordArray(message, bannedWords); + expect(matches.length).to.equal(bannedWords.length); + }); + }); +}); diff --git a/test/api/v3/integration/chat/POST-chat.test.js b/test/api/v3/integration/chat/POST-chat.test.js index 8334af8a07..d664d9114e 100644 --- a/test/api/v3/integration/chat/POST-chat.test.js +++ b/test/api/v3/integration/chat/POST-chat.test.js @@ -14,8 +14,6 @@ import { TAVERN_ID, } from '../../../../../website/server/models/group'; import { CHAT_FLAG_FROM_SHADOW_MUTE, MAX_MESSAGE_LENGTH } from '../../../../../website/common/script/constants'; -import { getMatchesByWordArray } from '../../../../../website/server/libs/stringUtils'; -import bannedWords from '../../../../../website/server/libs/bannedWords'; import guildsAllowingBannedWords from '../../../../../website/server/libs/guildsAllowingBannedWords'; import * as email from '../../../../../website/server/libs/email'; @@ -292,12 +290,6 @@ describe('POST /chat', () => { .that.includes(testBannedWords.join(', ')); }); - it('check all banned words are matched', async () => { - const message = bannedWords.join(',').replace(/\\/g, ''); - const matches = getMatchesByWordArray(message, bannedWords); - expect(matches.length).to.equal(bannedWords.length); - }); - it('does not error when bad word is suffix of a word', async () => { const wordAsSuffix = `prefix${testBannedWordMessage}`; const message = await user.post('/groups/habitrpg/chat', { message: wordAsSuffix }); diff --git a/website/server/libs/stringUtils.js b/website/server/libs/stringUtils.js index d319be3758..a7e4b08aa8 100644 --- a/website/server/libs/stringUtils.js +++ b/website/server/libs/stringUtils.js @@ -1,15 +1,12 @@ -import escapeRegExp from 'lodash/escapeRegExp'; - export function removePunctuationFromString (str) { return str.replace(/[.,/#!@$%^&;:{}=\-_`~()]/g, ' '); } +// NOTE: the wordsToMatch aren't escaped in order to support regular expressions, +// so this method should not be used if wordsToMatch contains unsanitized user input export function getMatchesByWordArray (str, wordsToMatch) { const matchedWords = []; - const wordRegexs = wordsToMatch.map(word => { - const escapedWord = escapeRegExp(word); - return new RegExp(`\\b([^a-z]+)?${escapedWord}([^a-z]+)?\\b`, 'i'); - }); + const wordRegexs = wordsToMatch.map(word => new RegExp(`\\b([^a-z]+)?${word}([^a-z]+)?\\b`, 'i')); for (let i = 0; i < wordRegexs.length; i += 1) { const regEx = wordRegexs[i]; const match = str.match(regEx); diff --git a/website/server/libs/user/validation.js b/website/server/libs/user/validation.js index 2ad4597c64..cbdc6487d0 100644 --- a/website/server/libs/user/validation.js +++ b/website/server/libs/user/validation.js @@ -1,12 +1,8 @@ -import escapeRegExp from 'lodash/escapeRegExp'; import bannedSlurs from '../bannedSlurs'; import { getMatchesByWordArray } from '../stringUtils'; import forbiddenUsernames from '../forbiddenUsernames'; -const bannedSlurRegexs = bannedSlurs.map(word => { - const escapedWord = escapeRegExp(word); - return new RegExp(`.*${escapedWord}.*`, 'i'); -}); +const bannedSlurRegexs = bannedSlurs.map(word => new RegExp(`.*${word}.*`, 'i')); export function nameContainsSlur (username) { for (let i = 0; i < bannedSlurRegexs.length; i += 1) {