Skip to content

[WP4] LIKE-family wildcard injection + unbounded IN expansion #194

Description

@shihyuho

此內容由 AI 產生(specification-mapper 全庫審查 2026-07-16.執行圖)。

Work package WP4 · findings: SEC-01, MAINT-03 · worst severity: medium · effort: S

From the 2026-07-16 whole-codebase review of branch jakarta (snapshot 7de4a33; modules mapper/ + starter/). Every finding below is CONFIRMED by independent adversarial verification. File:line coordinates are from the snapshot and may have drifted.

Findings

SEC-01 — LIKE-family specs concatenate user values into patterns without escaping % and _ (security, medium)

  • File: mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/Like.java:53 (plus siblings NotLike, StartingWith, EndingWith)
  • Evidence: the constructor builds "%" + value + "%" with no escaping, and toPredicate calls builder.like(path, pattern) without an escape character.
  • Failure scenario: a % submitted into a StartingWith-mapped field (e.g. a tenant/department prefix scoping filter) becomes a %%… pattern that matches everything — scoping bypass → data exposure; pathological patterns force full-scan LIKE → cheap DoS. Values are bound parameters, so this is wildcard-semantics leakage, not SQL injection.

MAINT-03 — In/NotIn expand unbounded user-supplied collections into a single IN (...) list (maintainability, low)

  • File: mapper/src/main/java/tw/com/softleader/data/jpa/spec/domain/In.java:64
  • Evidence: the whole user collection is expanded into one IN predicate; several RDBMS cap the element count (commonly 1000) and huge lists degrade plans.

Plan

  1. In all four LIKE-family specs (Like, NotLike, StartingWith, EndingWith), escape \, %, _ in the user value before composing the pattern, and switch to the escape-aware overloads builder.like(expr, pattern, '\\') / builder.notLike(expr, pattern, '\\').
  2. For In/NotIn, partition oversized collections into OR-combined IN chunks with a documented maximum chunk size (default 1000; the maintainer may tune per target RDBMS).
  3. Release note: consumers who deliberately passed raw wildcards through LIKE-family fields lose that (undocumented) behavior — document the change and the literal-match guarantee.
  4. Tests: values containing %, _, \ match literally through SpecMapper.toSpec; an In collection larger than the chunk size builds valid SQL and returns correct results.

Acceptance criteria

  • %/_ submitted through any LIKE-family spec match literally — the prefix-scope bypass no longer reproduces.
  • In with more values than the chunk size executes correctly.
  • New tests from step 4 pass; regression: make test green.

Metadata

Metadata

Assignees

Labels

status: ready-for-agentFully specified and ready for an autonomous AFK agent to implementtype: bugSomething isn't working

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions