From 32a3d4c9e04afc44144ca970101dc91dd9386abf Mon Sep 17 00:00:00 2001 From: long-agent Date: Sat, 18 Apr 2026 13:06:44 +0800 Subject: [PATCH] fix: P0-01 prevent LIKE injection in operation_log and device repos - operation_log.go Search(): add escapeLikePattern + ESCAPE clause - device.go ListAllCursor(): add escapeLikePattern + ESCAPE clause The ESCAPE clause is required for SQLite to properly interpret backslash as an escape character. --- internal/repository/device.go | 5 +++-- internal/repository/operation_log.go | 7 +++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/internal/repository/device.go b/internal/repository/device.go index 3251526..13e7c16 100644 --- a/internal/repository/device.go +++ b/internal/repository/device.go @@ -275,8 +275,9 @@ func (r *DeviceRepository) ListAllCursor(ctx context.Context, params *ListDevice query = query.Where("is_trusted = ?", *params.IsTrusted) } if params.Keyword != "" { - search := "%" + params.Keyword + "%" - query = query.Where("device_name LIKE ? OR ip LIKE ? OR location LIKE ?", search, search, search) + escapedKeyword := escapeLikePattern(params.Keyword) + pattern := "%" + escapedKeyword + "%" + query = query.Where("device_name LIKE ? ESCAPE '\\' OR ip LIKE ? ESCAPE '\\' OR location LIKE ? ESCAPE '\\'", pattern, pattern, pattern) } // Apply cursor condition for keyset navigation diff --git a/internal/repository/operation_log.go b/internal/repository/operation_log.go index 57e6672..14558a2 100644 --- a/internal/repository/operation_log.go +++ b/internal/repository/operation_log.go @@ -101,9 +101,12 @@ func (r *OperationLogRepository) DeleteOlderThan(ctx context.Context, days int) func (r *OperationLogRepository) Search(ctx context.Context, keyword string, offset, limit int) ([]*domain.OperationLog, int64, error) { var logs []*domain.OperationLog var total int64 + // 转义 LIKE 特殊字符,防止搜索被意外干扰 + escapedKeyword := escapeLikePattern(keyword) + pattern := "%" + escapedKeyword + "%" query := r.db.WithContext(ctx).Model(&domain.OperationLog{}). - Where("operation_name LIKE ? OR request_path LIKE ? OR operation_type LIKE ?", - "%"+keyword+"%", "%"+keyword+"%", "%"+keyword+"%") + Where("operation_name LIKE ? ESCAPE '\\' OR request_path LIKE ? ESCAPE '\\' OR operation_type LIKE ? ESCAPE '\\'", + pattern, pattern, pattern) if err := query.Count(&total).Error; err != nil { return nil, 0, err }