case 4716 - pick-list search text passed as SQL parameters

PickListSqlBuilder put the search text and the tag search text into the SQL
inside quotes with no escaping, reachable by any login (security review F18);
an apostrophe in a search also made the query fail. The builder now writes
@plq / @pltag and PickListFetcher adds them as Npgsql parameters (same %text%
match; wildcards typed by the user still apply).

Changelog: searching selection lists for text with an apostrophe now works.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-24 12:28:43 -07:00
parent e58ab2c100
commit b1944b7ca3
5 changed files with 17 additions and 9 deletions

View File

@@ -56,6 +56,11 @@ namespace AyaNova.PickList
//GET DATA RETURN ROWS
command.CommandText = q;
//case 4716: search texts go in as parameters (same %text% match as before, wildcards typed by the user still apply)
if (q.Contains("@plq"))
command.Parameters.Add(new Npgsql.NpgsqlParameter("plq", $"%{autoCompleteQuery}%"));
if (q.Contains("@pltag"))
command.Parameters.Add(new Npgsql.NpgsqlParameter("pltag", $"%{tagSpecificQuery}%"));
try
{
using (var dr = await command.ExecuteReaderAsync())

View File

@@ -104,13 +104,15 @@ namespace AyaNova.PickList
}
}
//case 4716: the search texts are SQL parameters (@plq, @pltag), added by PickListFetcher, never part of the SQL text
//PROCESS TAG SPECIFIC QUERY
//
if (HasTagSpecificQuery)
{
//get the tag column
AyaPickListFieldDefinition tagColumn = pickList.ColumnDefinitions.FirstOrDefault(z => z.ColumnDataType == UiFieldDataType.Tags);
TagSpecificWhereFragment = $"(array_to_string({tagColumn.GetSqlValueColumnName()},',') like '%{tagSpecificQuery}%')";
TagSpecificWhereFragment = $"(array_to_string({tagColumn.GetSqlValueColumnName()},',') like @pltag)";
}
@@ -150,9 +152,9 @@ namespace AyaNova.PickList
if (HasAutoCompleteQuery && !HasTagSpecificQuery)
{
if (ServerGlobalBizSettings.Cache.FilterCaseSensitive)
sWhere = $"(array_to_string({valueColumnName},',') like '%{autoCompleteQuery}%')";
sWhere = $"(array_to_string({valueColumnName},',') like @plq)";
else
sWhere = $"(lower(array_to_string({valueColumnName},',')) like lower('%{autoCompleteQuery}%'))";
sWhere = $"(lower(array_to_string({valueColumnName},',')) like lower(@plq))";
}
@@ -165,9 +167,9 @@ namespace AyaNova.PickList
lOrderBy.Add(valueColumnName);
if (HasAutoCompleteQuery)
if (ServerGlobalBizSettings.Cache.FilterCaseSensitive)
sWhere = $"({valueColumnName} like '%{autoCompleteQuery}%')";
sWhere = $"({valueColumnName} like @plq)";
else
sWhere = $"(lower({valueColumnName}) like lower('%{autoCompleteQuery}%'))";
sWhere = $"(lower({valueColumnName}) like lower(@plq))";
}
else
@@ -187,9 +189,9 @@ namespace AyaNova.PickList
//(cast (aworkorder.serial as text) like '%some%')
if (HasAutoCompleteQuery)
if (ServerGlobalBizSettings.Cache.FilterCaseSensitive)
sWhere = $"(cast ({valueColumnName} as text) like '%{autoCompleteQuery}%')";
sWhere = $"(cast ({valueColumnName} as text) like @plq)";
else
sWhere = $"(lower(cast ({valueColumnName} as text)) like lower('%{autoCompleteQuery}%'))";
sWhere = $"(lower(cast ({valueColumnName} as text)) like lower(@plq))";
}