Skip to content

fix(api): refactors the SQL LIKE pattern escaping logic to use a centralized utility function, ensuring consistent and secure handling of special characters across all database queries. - #7

Open
tomerqodo wants to merge 4 commits into
cursor_only-issues-20260113-cursor_completion_base_fixapi_refactors_the_sql_like_pattern_escaping_logic_to_use_a_centralized__utility_function_ensuring_consistent_and_secure_handling_of_special_characfrom
cursor_only-issues-20260113-cursor_completion_head_fixapi_refactors_the_sql_like_pattern_escaping_logic_to_use_a_centralized__utility_function_ensuring_consistent_and_secure_handling_of_special_charac
Open

fix(api): refactors the SQL LIKE pattern escaping logic to use a centralized utility function, ensuring consistent and secure handling of special characters across all database queries.#7
tomerqodo wants to merge 4 commits into
cursor_only-issues-20260113-cursor_completion_base_fixapi_refactors_the_sql_like_pattern_escaping_logic_to_use_a_centralized__utility_function_ensuring_consistent_and_secure_handling_of_special_characfrom
cursor_only-issues-20260113-cursor_completion_head_fixapi_refactors_the_sql_like_pattern_escaping_logic_to_use_a_centralized__utility_function_ensuring_consistent_and_secure_handling_of_special_charac

Conversation

@tomerqodo

@tomerqodo tomerqodo commented Jan 20, 2026

Copy link
Copy Markdown

Benchmark PR from qodo-benchmark#173


Note

Strengthens search safety/consistency by standardizing SQL LIKE escaping and updating related queries.

  • Adds libs.helper.escape_like_pattern and applies it to search filters in conversations, datasets segments, annotations, apps, tags, workflow logs, and metadata filtering
  • Updates vector backends: ClickZetta fallback LIKE now escapes patterns and IRIS LIKE search uses escaped patterns with ESCAPE '\'
  • Ensures all LIKE/ILIKE clauses specify an escape character and avoid unescaped wildcards
  • Expands tests: unit tests for escape_like_pattern; integration tests verifying literal matching of %, _, and \ across annotations, apps, tags, and workflow logs
  • Minor test refactors to delay AppService imports to avoid circular dependencies

Written by Cursor Bugbot for commit 0806191. Configure here.

NeatGuyCoding and others added 4 commits January 1, 2026 17:57
…ralized

utility function, ensuring consistent and secure handling of special characters
across all database queries.

Signed-off-by: NeatGuyCoding <15627489+NeatGuyCoding@users.noreply.github.com>
…logic

Signed-off-by: NeatGuyCoding <15627489+NeatGuyCoding@users.noreply.github.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 5 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

Comment thread api/libs/helper.py
if not pattern:
return pattern
# Escape backslash first, then percent and underscore
return pattern.replace("%", "\\%").replace("_", "\\_").replace("\\", "\\\\")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Escape order is wrong in escape_like_pattern function

High Severity

The escape_like_pattern function escapes characters in the wrong order. The comment says "Escape backslash first, then percent and underscore" but the code does the opposite - it escapes % and _ first, then \\ last. This causes already-escaped characters to be double-escaped. For example, input test\%_value produces test\\\\%\\_value instead of test\\\%\_value.

Fix in Cursor Fix in Web

query = query.where(
or_(
DocumentSegment.content.ilike(f"%{keyword}%"),
DocumentSegment.content.ilike(f"%{keyword}%", escape="\\"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unescaped keyword used in LIKE pattern

High Severity

The code creates escaped_keyword by calling escape_like_pattern(keyword) but then uses the original unescaped keyword variable in DocumentSegment.content.ilike(f"%{keyword}%", escape="\\"). This defeats the purpose of the escaping and leaves the query vulnerable to SQL injection via LIKE wildcards.

Fix in Cursor Fix in Web

case "end with":
filters.append(json_field.like(f"%{value}"))
escaped_value = escape_like_pattern(str(value))
filters.append(json_field.like(f"%{value}", escape="\\"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unescaped value used in "end with" LIKE pattern

High Severity

The "end with" case creates escaped_value by calling escape_like_pattern(str(value)) but then uses the original unescaped value variable in json_field.like(f"%{value}", escape="\\"). This bypasses the escaping protection entirely for the "end with" metadata filter condition.

Fix in Cursor Fix in Web


# Escape special characters in keyword to prevent SQL injection via LIKE wildcards
escaped_keyword = escape_like_pattern(keyword[:30])
keyword_like_val = f"%{keyword[:30]}%"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Escaped keyword created but never used

High Severity

The code creates escaped_keyword by calling escape_like_pattern(keyword[:30]) but then constructs keyword_like_val using the original unescaped keyword[:30]. The escaped_keyword variable is never used, completely bypassing the escaping intended to prevent SQL injection via LIKE wildcards.

Fix in Cursor Fix in Web

from libs.helper import escape_like_pattern

escaped_query = escape_like_pattern(query).replace("'", "''")
filter_clauses.append(f"{Field.CONTENT_KEY} LIKE '%{escaped_query}%' ESCAPE '\\\\'")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClickZetta ESCAPE clause has extra backslash

Medium Severity

The SQL ESCAPE clause uses ESCAPE '\\\\' which produces ESCAPE '\\' in SQL (two backslashes), but escape_like_pattern produces escapes using a single backslash (e.g., \%). Since ClickZetta is configured with quote mode where backslash is literal, this mismatch means the LIKE pattern escaping won't work correctly. The ESCAPE clause should use ESCAPE '\\' in Python to produce ESCAPE '\' in SQL.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants