diff options
| author | Johann150 <johann.galle@protonmail.com> | 2022-02-10 11:47:46 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-02-10 19:47:46 +0900 |
| commit | afb63049798dd0277cd9045eb00a16ab1228376b (patch) | |
| tree | c3a00837a7fc7e626f5632902cf894db326c7828 /packages/backend/src | |
| parent | Node v16.13.2 (#8281) (diff) | |
| download | sharkey-afb63049798dd0277cd9045eb00a16ab1228376b.tar.gz sharkey-afb63049798dd0277cd9045eb00a16ab1228376b.tar.bz2 sharkey-afb63049798dd0277cd9045eb00a16ab1228376b.zip | |
fix: regular expressions in word mutes (#8254)
* fix: handle regex exceptions for word mutes
* add i18n strings
Co-authored-by: rinsuki <428rinsuki+git@gmail.com>
* stricter input validation in backend
* add migration for hard mutes
* fix
* use correct regex library in migration
* use query builder to avoid SQL injection
Co-authored-by: Robin B <robflop98@outlook.com>
Co-authored-by: rinsuki <428rinsuki+git@gmail.com>
Diffstat (limited to 'packages/backend/src')
| -rw-r--r-- | packages/backend/src/misc/check-word-mute.ts | 31 | ||||
| -rw-r--r-- | packages/backend/src/server/api/endpoints/i/update.ts | 21 |
2 files changed, 38 insertions, 14 deletions
diff --git a/packages/backend/src/misc/check-word-mute.ts b/packages/backend/src/misc/check-word-mute.ts index e2e871dd2b..dedda3cdf6 100644 --- a/packages/backend/src/misc/check-word-mute.ts +++ b/packages/backend/src/misc/check-word-mute.ts @@ -11,26 +11,31 @@ type UserLike = { id: User['id']; }; -export async function checkWordMute(note: NoteLike, me: UserLike | null | undefined, mutedWords: string[][]): Promise<boolean> { +export async function checkWordMute(note: NoteLike, me: UserLike | null | undefined, mutedWords: Array<string | string[]>): Promise<boolean> { // 自分自身 if (me && (note.userId === me.id)) return false; - const words = mutedWords - // Clean up - .map(xs => xs.filter(x => x !== '')) - .filter(xs => xs.length > 0); - - if (words.length > 0) { + if (mutedWords.length > 0) { if (note.text == null) return false; - const matched = words.some(and => - and.every(keyword => { - const regexp = keyword.match(/^\/(.+)\/(.*)$/); - if (regexp) { + const matched = mutedWords.some(filter => { + if (Array.isArray(filter)) { + return filter.every(keyword => note.text!.includes(keyword)); + } else { + // represents RegExp + const regexp = filter.match(/^\/(.+)\/(.*)$/); + + // This should never happen due to input sanitisation. + if (!regexp) return false; + + try { return new RE2(regexp[1], regexp[2]).test(note.text!); + } catch (err) { + // This should never happen due to input sanitisation. + return false; } - return note.text!.includes(keyword); - })); + } + }); if (matched) return true; } diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index eb57aa2bfc..aec7bbd2e1 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -1,3 +1,4 @@ +const RE2 = require('re2'); import $ from 'cafy'; import * as mfm from 'mfm-js'; import { ID } from '@/misc/cafy-id'; @@ -117,7 +118,7 @@ export const meta = { }, mutedWords: { - validator: $.optional.arr($.arr($.str)), + validator: $.optional.arr($.either($.arr($.str.min(1)).min(1), $.str)), }, mutedInstances: { @@ -163,6 +164,12 @@ export const meta = { code: 'NO_SUCH_PAGE', id: '8e01b590-7eb9-431b-a239-860e086c408e', }, + + invalidRegexp: { + message: 'Invalid Regular Expression.', + code: 'INVALID_REGEXP', + id: '0d786918-10df-41cd-8f33-8dec7d9a89a5', + } }, res: { @@ -191,6 +198,18 @@ export default define(meta, async (ps, _user, token) => { if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId; if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId; if (ps.mutedWords !== undefined) { + // validate regular expression syntax + ps.mutedWords.filter(x => !Array.isArray(x)).forEach(x => { + const regexp = x.match(/^\/(.+)\/(.*)$/); + if (!regexp) throw new ApiError(meta.errors.invalidRegexp); + + try { + new RE2(regexp[1], regexp[2]); + } catch (err) { + throw new ApiError(meta.errors.invalidRegexp); + } + }); + profileUpdates.mutedWords = ps.mutedWords; profileUpdates.enableWordMute = ps.mutedWords.length > 0; } |