Fix SQLite LIKE wildcard escaping in IP filter queries

- Add escape_like() helper to escape % and _ wildcards in LIKE queries
- Update fail2ban_db_repo.get_history_page() to use escaping
- Update history_archive_repo.get_archived_history() to use escaping
- Add ESCAPE clause to all LIKE queries
- Add comprehensive unit tests for escape_like function
- Add integration tests for LIKE wildcard handling
- Document LIKE escaping best practices in Backend-Development.md

Fixes TASK-017: Prevent unintended LIKE matches when IP filter contains
special characters like underscore or percent sign.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-04-26 14:07:49 +02:00
parent 94bdabe622
commit 667ab674ca
7 changed files with 234 additions and 4 deletions

View File

@@ -15,6 +15,8 @@ from typing import TYPE_CHECKING
import aiosqlite
from app.utils.fail2ban_db_utils import escape_like
if TYPE_CHECKING:
from collections.abc import Iterable
@@ -321,8 +323,8 @@ async def get_history_page(
params.append(jail)
if ip_filter is not None:
wheres.append("ip LIKE ?")
params.append(f"{ip_filter}%")
wheres.append("ip LIKE ? ESCAPE '\\'")
params.append(f"{escape_like(ip_filter)}%")
origin_clause, origin_params = _origin_sql_filter(origin)
if origin_clause:

View File

@@ -10,6 +10,7 @@ import datetime
from typing import TYPE_CHECKING, Any
from app.models.ban import BLOCKLIST_JAIL, BanOrigin
from app.utils.fail2ban_db_utils import escape_like
if TYPE_CHECKING:
import aiosqlite
@@ -76,8 +77,8 @@ async def get_archived_history(
wheres.append(f"ip IN ({placeholder})")
params.extend(ip_filter)
else:
wheres.append("ip LIKE ?")
params.append(f"{ip_filter}%")
wheres.append("ip LIKE ? ESCAPE '\\'")
params.append(f"{escape_like(ip_filter)}%")
if origin == "blocklist":
wheres.append("jail = ?")