From 54eb8f613bf808eabad2253f9ca3b3788b27babb Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Sun, 8 Jan 2023 20:32:17 +0900 Subject: [PATCH 1/3] fix: Escape SQL LIKE * SQL LIKE escape --- .../server/api/endpoints/admin/emoji/list-remote.ts | 3 ++- .../src/server/api/endpoints/admin/emoji/list.ts | 3 ++- .../src/server/api/endpoints/admin/show-users.ts | 3 ++- .../src/server/api/endpoints/federation/instances.ts | 3 ++- .../src/server/api/endpoints/hashtags/search.ts | 3 ++- .../backend/src/server/api/endpoints/notes/search.ts | 3 ++- .../endpoints/users/search-by-username-and-host.ts | 11 ++++++----- .../backend/src/server/api/endpoints/users/search.ts | 9 +++++---- 8 files changed, 23 insertions(+), 15 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts index 07d70365d..dac752d3a 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts @@ -2,6 +2,7 @@ import define from "../../../define.js"; import { Emojis } from "@/models/index.js"; import { toPuny } from "@/misc/convert-host.js"; import { makePaginationQuery } from "../../../common/make-pagination-query.js"; +import { sqlLikeEscape } from "@/misc/sql-like-escape"; export const meta = { tags: ["admin"], @@ -106,7 +107,7 @@ export default define(meta, paramDef, async (ps) => { } if (ps.query) { - q.andWhere("emoji.name like :query", { query: `%${ps.query}%` }); + q.andWhere('emoji.name like :query', { query: `%${sqlLikeEscape(ps.query)}%` }); } const emojis = await q.orderBy("emoji.id", "DESC").take(ps.limit).getMany(); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts index 9390dfb20..5ac110d6f 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts @@ -2,6 +2,7 @@ import define from "../../../define.js"; import { Emojis } from "@/models/index.js"; import { makePaginationQuery } from "../../../common/make-pagination-query.js"; import type { Emoji } from "@/models/entities/emoji.js"; +//import { sqlLikeEscape } from "@/misc/sql-like-escape"; export const meta = { tags: ["admin"], @@ -96,7 +97,7 @@ export default define(meta, paramDef, async (ps) => { let emojis: Emoji[]; if (ps.query) { - //q.andWhere('emoji.name ILIKE :q', { q: `%${ps.query}%` }); + //q.andWhere('emoji.name ILIKE :q', { q: `%${sqlLikeEscape(ps.query)}%` }); //const emojis = await q.take(ps.limit).getMany(); emojis = await q.getMany(); diff --git a/packages/backend/src/server/api/endpoints/admin/show-users.ts b/packages/backend/src/server/api/endpoints/admin/show-users.ts index 868df9dc9..1e76e0846 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-users.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-users.ts @@ -1,5 +1,6 @@ import { Users } from "@/models/index.js"; import define from "../../define.js"; +import { sqlLikeEscape } from "@/misc/sql-like-escape"; export const meta = { tags: ["admin"], @@ -106,7 +107,7 @@ export default define(meta, paramDef, async (ps, me) => { if (ps.username) { query.andWhere("user.usernameLower like :username", { - username: `${ps.username.toLowerCase()}%`, + username: `${sqlLikeEscape(ps.username.toLowerCase())}%`, }); } diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts index 646f38282..34af50f36 100644 --- a/packages/backend/src/server/api/endpoints/federation/instances.ts +++ b/packages/backend/src/server/api/endpoints/federation/instances.ts @@ -2,6 +2,7 @@ import config from "@/config/index.js"; import define from "../../define.js"; import { Instances } from "@/models/index.js"; import { fetchMeta } from "@/misc/fetch-meta.js"; +import { sqlLikeEscape } from "@/misc/sql-like-escape"; export const meta = { tags: ["federation"], @@ -178,7 +179,7 @@ export default define(meta, paramDef, async (ps, me) => { if (ps.host) { query.andWhere("instance.host like :host", { - host: `%${ps.host.toLowerCase()}%`, + host: `%${sqlLikeEscape(ps.host.toLowerCase())}%`, }); } diff --git a/packages/backend/src/server/api/endpoints/hashtags/search.ts b/packages/backend/src/server/api/endpoints/hashtags/search.ts index 95bc608ec..49cc2aca1 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/search.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/search.ts @@ -1,5 +1,6 @@ import define from "../../define.js"; import { Hashtags } from "@/models/index.js"; +import { sqlLikeEscape } from "@/misc/sql-like-escape"; export const meta = { tags: ["hashtags"], @@ -31,7 +32,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps) => { const hashtags = await Hashtags.createQueryBuilder("tag") - .where("tag.name like :q", { q: `${ps.query.toLowerCase()}%` }) + .where("tag.name like :q", { q: `${sqlLikeEscape(ps.query.toLowerCase())}%` }) .orderBy("tag.count", "DESC") .groupBy("tag.id") .take(ps.limit) diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts index 8f563c384..6b151efef 100644 --- a/packages/backend/src/server/api/endpoints/notes/search.ts +++ b/packages/backend/src/server/api/endpoints/notes/search.ts @@ -9,6 +9,7 @@ import { makePaginationQuery } from "../../common/make-pagination-query.js"; import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; +import { sqlLikeEscape } from "@/misc/sql-like-escape"; export const meta = { tags: ["notes"], @@ -77,7 +78,7 @@ export default define(meta, paramDef, async (ps, me) => { } query - .andWhere("note.text ILIKE :q", { q: `%${ps.query}%` }) + .andWhere("note.text ILIKE :q", { q: `%${sqlLikeEscape(ps.query)}%` }) .innerJoinAndSelect("note.user", "user") .leftJoinAndSelect("user.avatar", "avatar") .leftJoinAndSelect("user.banner", "banner") diff --git a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts index 99aa2f1af..344948101 100644 --- a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts +++ b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts @@ -3,6 +3,7 @@ import { Followings, Users } from "@/models/index.js"; import { USER_ACTIVE_THRESHOLD } from "@/const.js"; import type { User } from "@/models/entities/user.js"; import define from "../../define.js"; +import { sqlLikeEscape } from "@/misc/sql-like-escape"; export const meta = { tags: ["users"], @@ -44,11 +45,11 @@ export default define(meta, paramDef, async (ps, me) => { if (ps.host) { const q = Users.createQueryBuilder("user") .where("user.isSuspended = FALSE") - .andWhere("user.host LIKE :host", { host: `${ps.host.toLowerCase()}%` }); + .andWhere("user.host LIKE :host", { host: `${sqlLikeEscape(ps.host.toLowerCase())}%` }); if (ps.username) { q.andWhere("user.usernameLower LIKE :username", { - username: `${ps.username.toLowerCase()}%`, + username: `${sqlLikeEscape(ps.username.toLowerCase())}%`, }); } @@ -71,7 +72,7 @@ export default define(meta, paramDef, async (ps, me) => { .andWhere("user.id != :meId", { meId: me.id }) .andWhere("user.isSuspended = FALSE") .andWhere("user.usernameLower LIKE :username", { - username: `${ps.username.toLowerCase()}%`, + username: `${sqlLikeEscape(ps.username.toLowerCase())}%`, }) .andWhere( new Brackets((qb) => { @@ -95,7 +96,7 @@ export default define(meta, paramDef, async (ps, me) => { .andWhere("user.id != :meId", { meId: me.id }) .andWhere("user.isSuspended = FALSE") .andWhere("user.usernameLower LIKE :username", { - username: `${ps.username.toLowerCase()}%`, + username: `${sqlLikeEscape(ps.username.toLowerCase())}%`, }) .andWhere("user.updatedAt IS NOT NULL"); @@ -112,7 +113,7 @@ export default define(meta, paramDef, async (ps, me) => { users = await Users.createQueryBuilder("user") .where("user.isSuspended = FALSE") .andWhere("user.usernameLower LIKE :username", { - username: `${ps.username.toLowerCase()}%`, + username: `${sqlLikeEscape(ps.username.toLowerCase())}%`, }) .andWhere("user.updatedAt IS NOT NULL") .orderBy("user.updatedAt", "DESC") diff --git a/packages/backend/src/server/api/endpoints/users/search.ts b/packages/backend/src/server/api/endpoints/users/search.ts index db687a107..02bdf6d4b 100644 --- a/packages/backend/src/server/api/endpoints/users/search.ts +++ b/packages/backend/src/server/api/endpoints/users/search.ts @@ -2,6 +2,7 @@ import { Brackets } from "typeorm"; import { UserProfiles, Users } from "@/models/index.js"; import type { User } from "@/models/entities/user.js"; import define from "../../define.js"; +import { sqlLikeEscape } from "@/misc/sql-like-escape"; export const meta = { tags: ["users"], @@ -50,7 +51,7 @@ export default define(meta, paramDef, async (ps, me) => { if (isUsername) { const usernameQuery = Users.createQueryBuilder("user") .where("user.usernameLower LIKE :username", { - username: `${ps.query.replace("@", "").toLowerCase()}%`, + username: `${sqlLikeEscape(ps.query.replace("@", "").toLowerCase())}%`, }) .andWhere( new Brackets((qb) => { @@ -77,12 +78,12 @@ export default define(meta, paramDef, async (ps, me) => { const nameQuery = Users.createQueryBuilder("user") .where( new Brackets((qb) => { - qb.where("user.name ILIKE :query", { query: `%${ps.query}%` }); + qb.where("user.name ILIKE :query", { query: `%${sqlLikeEscape(ps.query)}%` }); // Also search username if it qualifies as username if (Users.validateLocalUsername(ps.query)) { qb.orWhere("user.usernameLower LIKE :username", { - username: `%${ps.query.toLowerCase()}%`, + username: `%${sqlLikeEscape(ps.query.toLowerCase())}%`, }); } }), @@ -113,7 +114,7 @@ export default define(meta, paramDef, async (ps, me) => { const profQuery = UserProfiles.createQueryBuilder("prof") .select("prof.userId") .where("prof.description ILIKE :query", { - query: `%${ps.query}%`, + query: `%${sqlLikeEscape(ps.query)}%`, }); if (ps.origin === "local") { From c6d10e705a815f652238954360894acc9f391378 Mon Sep 17 00:00:00 2001 From: naskya Date: Tue, 23 May 2023 14:07:35 +0900 Subject: [PATCH 2/3] .js --- .../backend/src/server/api/endpoints/admin/emoji/list-remote.ts | 2 +- packages/backend/src/server/api/endpoints/admin/emoji/list.ts | 2 +- packages/backend/src/server/api/endpoints/admin/show-users.ts | 2 +- .../backend/src/server/api/endpoints/federation/instances.ts | 2 +- packages/backend/src/server/api/endpoints/hashtags/search.ts | 2 +- packages/backend/src/server/api/endpoints/notes/search.ts | 2 +- .../server/api/endpoints/users/search-by-username-and-host.ts | 2 +- packages/backend/src/server/api/endpoints/users/search.ts | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts index dac752d3a..721fd280a 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts @@ -2,7 +2,7 @@ import define from "../../../define.js"; import { Emojis } from "@/models/index.js"; import { toPuny } from "@/misc/convert-host.js"; import { makePaginationQuery } from "../../../common/make-pagination-query.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape"; +import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; export const meta = { tags: ["admin"], diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts index 5ac110d6f..f8269588c 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts @@ -2,7 +2,7 @@ import define from "../../../define.js"; import { Emojis } from "@/models/index.js"; import { makePaginationQuery } from "../../../common/make-pagination-query.js"; import type { Emoji } from "@/models/entities/emoji.js"; -//import { sqlLikeEscape } from "@/misc/sql-like-escape"; +//import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; export const meta = { tags: ["admin"], diff --git a/packages/backend/src/server/api/endpoints/admin/show-users.ts b/packages/backend/src/server/api/endpoints/admin/show-users.ts index 1e76e0846..b777bd26d 100644 --- a/packages/backend/src/server/api/endpoints/admin/show-users.ts +++ b/packages/backend/src/server/api/endpoints/admin/show-users.ts @@ -1,6 +1,6 @@ import { Users } from "@/models/index.js"; import define from "../../define.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape"; +import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; export const meta = { tags: ["admin"], diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts index 34af50f36..fa1a41531 100644 --- a/packages/backend/src/server/api/endpoints/federation/instances.ts +++ b/packages/backend/src/server/api/endpoints/federation/instances.ts @@ -2,7 +2,7 @@ import config from "@/config/index.js"; import define from "../../define.js"; import { Instances } from "@/models/index.js"; import { fetchMeta } from "@/misc/fetch-meta.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape"; +import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; export const meta = { tags: ["federation"], diff --git a/packages/backend/src/server/api/endpoints/hashtags/search.ts b/packages/backend/src/server/api/endpoints/hashtags/search.ts index 49cc2aca1..31bee1219 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/search.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/search.ts @@ -1,6 +1,6 @@ import define from "../../define.js"; import { Hashtags } from "@/models/index.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape"; +import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; export const meta = { tags: ["hashtags"], diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts index 6b151efef..93392acdd 100644 --- a/packages/backend/src/server/api/endpoints/notes/search.ts +++ b/packages/backend/src/server/api/endpoints/notes/search.ts @@ -9,7 +9,7 @@ import { makePaginationQuery } from "../../common/make-pagination-query.js"; import { generateVisibilityQuery } from "../../common/generate-visibility-query.js"; import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js"; import { generateBlockedUserQuery } from "../../common/generate-block-query.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape"; +import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; export const meta = { tags: ["notes"], diff --git a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts index 344948101..1776c24e2 100644 --- a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts +++ b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts @@ -3,7 +3,7 @@ import { Followings, Users } from "@/models/index.js"; import { USER_ACTIVE_THRESHOLD } from "@/const.js"; import type { User } from "@/models/entities/user.js"; import define from "../../define.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape"; +import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; export const meta = { tags: ["users"], diff --git a/packages/backend/src/server/api/endpoints/users/search.ts b/packages/backend/src/server/api/endpoints/users/search.ts index 02bdf6d4b..9676c0fe2 100644 --- a/packages/backend/src/server/api/endpoints/users/search.ts +++ b/packages/backend/src/server/api/endpoints/users/search.ts @@ -2,7 +2,7 @@ import { Brackets } from "typeorm"; import { UserProfiles, Users } from "@/models/index.js"; import type { User } from "@/models/entities/user.js"; import define from "../../define.js"; -import { sqlLikeEscape } from "@/misc/sql-like-escape"; +import { sqlLikeEscape } from "@/misc/sql-like-escape.js"; export const meta = { tags: ["users"], From b560145259cdb6a9e73c34459064b3bdbf4ff3b5 Mon Sep 17 00:00:00 2001 From: naskya Date: Tue, 23 May 2023 14:11:03 +0900 Subject: [PATCH 3/3] Format --- .../src/server/api/endpoints/admin/emoji/list-remote.ts | 4 +++- packages/backend/src/server/api/endpoints/hashtags/search.ts | 4 +++- .../server/api/endpoints/users/search-by-username-and-host.ts | 4 +++- packages/backend/src/server/api/endpoints/users/search.ts | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts index 721fd280a..6252e7e92 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts @@ -107,7 +107,9 @@ export default define(meta, paramDef, async (ps) => { } if (ps.query) { - q.andWhere('emoji.name like :query', { query: `%${sqlLikeEscape(ps.query)}%` }); + q.andWhere("emoji.name like :query", { + query: `%${sqlLikeEscape(ps.query)}%`, + }); } const emojis = await q.orderBy("emoji.id", "DESC").take(ps.limit).getMany(); diff --git a/packages/backend/src/server/api/endpoints/hashtags/search.ts b/packages/backend/src/server/api/endpoints/hashtags/search.ts index 31bee1219..cde586af0 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/search.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/search.ts @@ -32,7 +32,9 @@ export const paramDef = { export default define(meta, paramDef, async (ps) => { const hashtags = await Hashtags.createQueryBuilder("tag") - .where("tag.name like :q", { q: `${sqlLikeEscape(ps.query.toLowerCase())}%` }) + .where("tag.name like :q", { + q: `${sqlLikeEscape(ps.query.toLowerCase())}%`, + }) .orderBy("tag.count", "DESC") .groupBy("tag.id") .take(ps.limit) diff --git a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts index 1776c24e2..eeccf6938 100644 --- a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts +++ b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts @@ -45,7 +45,9 @@ export default define(meta, paramDef, async (ps, me) => { if (ps.host) { const q = Users.createQueryBuilder("user") .where("user.isSuspended = FALSE") - .andWhere("user.host LIKE :host", { host: `${sqlLikeEscape(ps.host.toLowerCase())}%` }); + .andWhere("user.host LIKE :host", { + host: `${sqlLikeEscape(ps.host.toLowerCase())}%`, + }); if (ps.username) { q.andWhere("user.usernameLower LIKE :username", { diff --git a/packages/backend/src/server/api/endpoints/users/search.ts b/packages/backend/src/server/api/endpoints/users/search.ts index 9676c0fe2..2d84d5bfe 100644 --- a/packages/backend/src/server/api/endpoints/users/search.ts +++ b/packages/backend/src/server/api/endpoints/users/search.ts @@ -78,7 +78,9 @@ export default define(meta, paramDef, async (ps, me) => { const nameQuery = Users.createQueryBuilder("user") .where( new Brackets((qb) => { - qb.where("user.name ILIKE :query", { query: `%${sqlLikeEscape(ps.query)}%` }); + qb.where("user.name ILIKE :query", { + query: `%${sqlLikeEscape(ps.query)}%`, + }); // Also search username if it qualifies as username if (Users.validateLocalUsername(ps.query)) {