Follow-up to PR #10.
internal/db/turns.go:325 builds a LIKE query with the user-supplied fragment inserted verbatim between two % wildcards:
```go
rows, err := db.Query(`
SELECT DISTINCT tool_name
FROM tool_uses
WHERE tool_name LIKE '%' || ? || '%'
ORDER BY tool_name
LIMIT ?`, fragment, limit)
```
If `fragment` contains `%` or `_` (SQLite LIKE metacharacters), they leak into the pattern:
- `tool:foo_bar` → matches `tool_name LIKE '%foo_bar%'` which treats `_` as a single-char wildcard, matching `foolbar`, `fooxbar`, etc.
- `tool:100%` → `'%100%%'` behaves as `starts with anything containing 100`.
Real tool names in ccvault don't contain these characters today (`Bash`, `Read`, `mcp__foo__bar`, etc.), so the practical exposure is essentially zero. But the hygiene should be there.
Fix
Escape `%`, `_`, and `\` in `fragment` before passing to LIKE, and add `ESCAPE '\\'` clause. Or use `INSTR(tool_name, ?)` which does not interpret metacharacters at all — arguably cleaner for a substring search.
Test
Add a case to `TestDB_GetToolNamesLike` in `internal/db/db_test.go` that seeds `toolX`, `toolY`, `toolZ`, queries with fragment `_`, and asserts zero results.
Follow-up to PR #10.
internal/db/turns.go:325builds a LIKE query with the user-supplied fragment inserted verbatim between two%wildcards:```go
rows, err := db.Query(`
SELECT DISTINCT tool_name
FROM tool_uses
WHERE tool_name LIKE '%' || ? || '%'
ORDER BY tool_name
LIMIT ?`, fragment, limit)
```
If `fragment` contains `%` or `_` (SQLite LIKE metacharacters), they leak into the pattern:
Real tool names in ccvault don't contain these characters today (`Bash`, `Read`, `mcp__foo__bar`, etc.), so the practical exposure is essentially zero. But the hygiene should be there.
Fix
Escape `%`, `_`, and `\` in `fragment` before passing to LIKE, and add `ESCAPE '\\'` clause. Or use `INSTR(tool_name, ?)` which does not interpret metacharacters at all — arguably cleaner for a substring search.
Test
Add a case to `TestDB_GetToolNamesLike` in `internal/db/db_test.go` that seeds `toolX`, `toolY`, `toolZ`, queries with fragment `_`, and asserts zero results.