Skip to content

fix(bestool): reject a backslash in a snippet name, not a trailing percent (audit M19) - #442

Draft
passcod wants to merge 1 commit into
mainfrom
claude/pr-370-fix-m19-snippet-name-check
Draft

fix(bestool): reject a backslash in a snippet name, not a trailing percent (audit M19)#442
passcod wants to merge 1 commit into
mainfrom
claude/pr-370-fix-m19-snippet-name-check

Conversation

@passcod

@passcod passcod commented Aug 1, 2026

Copy link
Copy Markdown
Member

Fixes M19 (medium) from the audit in #370.

The bug

Backslash is LIKE's default escape character, so name NOT LIKE '%\%' reads as "does not end in a literal percent sign" — the opposite of the comment directly above it. Verified on Postgres 16:

expression result
'foo\bar' LIKE '%\%' false — backslash names were accepted
'top100%' LIKE '%\%' true — percent names were rejected
'foo\bar' LIKE '%\\%' true
'top100%' LIKE '%\\%' false

So the one clause guarding against backslashes let them through, and a perfectly reasonable name like top100% was rejected with a raw constraint 500. Names become client-side filenames on Windows bestool, which is why backslash is on the forbidden list at all; a percent sign never was. There's no app-level validation, so this CHECK is the only guard.

The fix

A migration replacing the constraint with '%\\%'.

NOT VALID, deliberately. The corrected clause is enforced on every insert and update from here on, but existing rows aren't scanned. A legacy name containing a backslash — accepted for as long as this constraint has been wrong — would otherwise fail the migration and block the deploy. Once the fleet is known clean, ALTER TABLE bestool_snippets VALIDATE CONSTRAINT valid_snippet_name; completes it without taking a write lock. Happy to make it a plain ADD CONSTRAINT instead if you'd rather find out loudly.

Tests

New crates/database/tests/it/snippet_name_constraint.rs:

  • a_backslash_in_a_name_is_rejected
  • a_percent_sign_in_a_name_is_allowed
  • the_other_forbidden_names_are_still_rejected — spaces, . / < > : " ' | ? *, and the Windows reserved names, plus an ordinary name that must be accepted.

The first two are confirmed to fail against the old constraint, one in each direction.


Generated by Claude Code

…rcent

Backslash is LIKE's default escape character, so `name NOT LIKE '%\%'` reads
as "does not end in a literal percent sign" — the opposite of the comment
directly above it. Verified on Postgres 16: `'foo\bar' LIKE '%\%'` is false
and `'top100%' LIKE '%\%'` is true, while the intended `'%\\%'` gives true
and false.

So the one clause guarding against backslashes accepted them, and a
legitimate name like `top100%` was rejected with a raw constraint 500. Names
become client-side filenames on Windows bestool, which is why backslash is on
the list at all; a percent sign never was. There's no app-level validation,
so this CHECK is the only guard.

Added NOT VALID: the corrected clause applies to every insert and update from
here on, but existing rows aren't scanned. A legacy backslash name — accepted
for as long as this constraint has been wrong — would otherwise fail the
migration and block the deploy. `VALIDATE CONSTRAINT` finishes the job once
the fleet is known clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SGfH1cdFKPnKpM7ytRThft
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