diff options
| author | MeiMei <30769358+mei23@users.noreply.github.com> | 2023-01-08 20:32:17 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-01-08 20:32:17 +0900 |
| commit | 10e526ba5682fef9488d1d38ba5dfcda38619673 (patch) | |
| tree | 1677ade360e317be70200050cb67b0957f35ebca /packages/backend/src/server/api/endpoints/users | |
| parent | fix following chart (diff) | |
| download | sharkey-10e526ba5682fef9488d1d38ba5dfcda38619673.tar.gz sharkey-10e526ba5682fef9488d1d38ba5dfcda38619673.tar.bz2 sharkey-10e526ba5682fef9488d1d38ba5dfcda38619673.zip | |
fix: Escape SQL LIKE (#9493)
* SQL LIKE escape
* CHANGELOG
Diffstat (limited to 'packages/backend/src/server/api/endpoints/users')
| -rw-r--r-- | packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts | 11 | ||||
| -rw-r--r-- | packages/backend/src/server/api/endpoints/users/search.ts | 9 |
2 files changed, 11 insertions, 9 deletions
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 f13df3ee9d..029b1e91c3 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 @@ -6,6 +6,7 @@ import type { User } from '@/models/entities/User.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; +import { sqlLikeEscape } from '@/misc/sql-like-escape'; export const meta = { tags: ['users'], @@ -59,10 +60,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { if (ps.host) { const q = this.usersRepository.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() + '%' }); + q.andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' }); } q.andWhere('user.updatedAt IS NOT NULL'); @@ -83,7 +84,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { .where(`user.id IN (${ followingQuery.getQuery() })`) .andWhere('user.id != :meId', { meId: me.id }) .andWhere('user.isSuspended = FALSE') - .andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' }) + .andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' }) .andWhere(new Brackets(qb => { qb .where('user.updatedAt IS NULL') .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); @@ -101,7 +102,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { .where(`user.id NOT IN (${ followingQuery.getQuery() })`) .andWhere('user.id != :meId', { meId: me.id }) .andWhere('user.isSuspended = FALSE') - .andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' }) + .andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' }) .andWhere('user.updatedAt IS NOT NULL'); otherQuery.setParameters(followingQuery.getParameters()); @@ -116,7 +117,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { } else { users = await this.usersRepository.createQueryBuilder('user') .where('user.isSuspended = FALSE') - .andWhere('user.usernameLower LIKE :username', { username: ps.username.toLowerCase() + '%' }) + .andWhere('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.username.toLowerCase()) + '%' }) .andWhere('user.updatedAt IS NOT NULL') .orderBy('user.updatedAt', 'DESC') .take(ps.limit - users.length) diff --git a/packages/backend/src/server/api/endpoints/users/search.ts b/packages/backend/src/server/api/endpoints/users/search.ts index ba07714972..25bd621269 100644 --- a/packages/backend/src/server/api/endpoints/users/search.ts +++ b/packages/backend/src/server/api/endpoints/users/search.ts @@ -5,6 +5,7 @@ import type { User } from '@/models/entities/User.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DI } from '@/di-symbols.js'; +import { sqlLikeEscape } from '@/misc/sql-like-escape'; export const meta = { tags: ['users'], @@ -57,7 +58,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { if (isUsername) { const usernameQuery = this.usersRepository.createQueryBuilder('user') - .where('user.usernameLower LIKE :username', { username: ps.query.replace('@', '').toLowerCase() + '%' }) + .where('user.usernameLower LIKE :username', { username: sqlLikeEscape(ps.query.replace('@', '').toLowerCase()) + '%' }) .andWhere(new Brackets(qb => { qb .where('user.updatedAt IS NULL') .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); @@ -78,11 +79,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { } else { const nameQuery = this.usersRepository.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 (this.userEntityService.validateLocalUsername(ps.query)) { - qb.orWhere('user.usernameLower LIKE :username', { username: '%' + ps.query.toLowerCase() + '%' }); + qb.orWhere('user.usernameLower LIKE :username', { username: '%' + sqlLikeEscape(ps.query.toLowerCase()) + '%' }); } })) .andWhere(new Brackets(qb => { qb @@ -106,7 +107,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { if (users.length < ps.limit) { const profQuery = this.userProfilesRepository.createQueryBuilder('prof') .select('prof.userId') - .where('prof.description ILIKE :query', { query: '%' + ps.query + '%' }); + .where('prof.description ILIKE :query', { query: '%' + sqlLikeEscape(ps.query) + '%' }); if (ps.origin === 'local') { profQuery.andWhere('prof.userHost IS NULL'); |