From a37d27ece343d395559c2c3a09b97e701036005e Mon Sep 17 00:00:00 2001 From: x032205 Date: Fri, 14 Nov 2025 20:33:50 -0500 Subject: [PATCH] escape special characters for ILIKE search --- backend/src/ee/services/pam-account/pam-account-dal.ts | 9 ++++++--- backend/src/ee/services/pam-folder/pam-folder-dal.ts | 4 +++- backend/src/ee/services/pam-resource/pam-resource-dal.ts | 7 +++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/backend/src/ee/services/pam-account/pam-account-dal.ts b/backend/src/ee/services/pam-account/pam-account-dal.ts index 5ee805ce1..b9f52b204 100644 --- a/backend/src/ee/services/pam-account/pam-account-dal.ts +++ b/backend/src/ee/services/pam-account/pam-account-dal.ts @@ -50,11 +50,14 @@ export const pamAccountDALFactory = (db: TDbClient) => { } if (search) { + // escape special characters (`%`, `_`) and the escape character itself (`\`) + const escapedSearch = search.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_"); + const pattern = `%${escapedSearch}%`; void query.where((q) => { void q - .whereILike(`${TableName.PamAccount}.name`, `%${search}%`) - .orWhereILike(`${TableName.PamResource}.name`, `%${search}%`) - .orWhereILike(`${TableName.PamAccount}.description`, `%${search}%`); + .whereRaw(`??.?? ILIKE ? ESCAPE '\\'`, [TableName.PamAccount, "name", pattern]) + .orWhereRaw(`??.?? ILIKE ? ESCAPE '\\'`, [TableName.PamResource, "name", pattern]) + .orWhereRaw(`??.?? ILIKE ? ESCAPE '\\'`, [TableName.PamAccount, "description", pattern]); }); } diff --git a/backend/src/ee/services/pam-folder/pam-folder-dal.ts b/backend/src/ee/services/pam-folder/pam-folder-dal.ts index 3566ff5f9..0b8aa8f60 100644 --- a/backend/src/ee/services/pam-folder/pam-folder-dal.ts +++ b/backend/src/ee/services/pam-folder/pam-folder-dal.ts @@ -43,7 +43,9 @@ export const pamFolderDALFactory = (db: TDbClient) => { } if (search) { - void query.whereILike(`${TableName.PamFolder}.name`, `%${search}%`); + // escape special characters (`%`, `_`) and the escape character itself (`\`) + const escapedSearch = search.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_"); + void query.whereRaw(`??.?? ILIKE ? ESCAPE '\\'`, [TableName.PamFolder, "name", `%${escapedSearch}%`]); } const countQuery = query.clone().count("*", { as: "count" }).first(); diff --git a/backend/src/ee/services/pam-resource/pam-resource-dal.ts b/backend/src/ee/services/pam-resource/pam-resource-dal.ts index 3b7e17499..7205542ed 100644 --- a/backend/src/ee/services/pam-resource/pam-resource-dal.ts +++ b/backend/src/ee/services/pam-resource/pam-resource-dal.ts @@ -47,10 +47,13 @@ export const pamResourceDALFactory = (db: TDbClient) => { const query = dbInstance(TableName.PamResource).where(`${TableName.PamResource}.projectId`, projectId); if (search) { + // escape special characters (`%`, `_`) and the escape character itself (`\`) + const escapedSearch = search.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_"); + const pattern = `%${escapedSearch}%`; void query.where((q) => { void q - .whereILike(`${TableName.PamResource}.name`, `%${search}%`) - .orWhereILike(`${TableName.PamResource}.resourceType`, `%${search}%`); + .whereRaw(`??.?? ILIKE ? ESCAPE '\\'`, [TableName.PamResource, "name", pattern]) + .orWhereRaw(`??.?? ILIKE ? ESCAPE '\\'`, [TableName.PamResource, "resourceType", pattern]); }); }