fix: anchor Label title validation with \z instead of \Z (#15443)
## Description This isn't tied to an open issue — I found it by extrapolating from the bug class fixed in #15415 ("fix: anchor contact phone number validation"), which fixed a `Contact#phone_number` format validation that was missing a leading `\A` anchor. That made me audit every hand-written regex-based validation in the codebase for the same class of anchoring mistake (`format: { with: ... }` validators, plus `match?`/`=~` calls used for validation-style checks, across `app/`, `enterprise/`, and `lib/`). Everything else was already correctly anchored. One real instance of the *sibling* mistake remains: `RegexHelper::UNICODE_CHARACTER_NUMBER_HYPHEN_UNDERSCORE` (used only by `Label#title`'s format validation) is `/\A[\p{L}\p{N}]+[\p{L}\p{N}_-]+\Z/` — note `\Z` (capital), not `\z`. Unlike `\z`, `\Z` also matches just before a single trailing `"\n"` at the end of the string. The surrounding comment documents the intended character set (unicode letters/numbers/underscore/hyphen, not starting with `_`/`-`) and says nothing about tolerating a trailing newline, so this reads as an unintentional choice of anchor rather than a deliberate one. Concretely: `Label.new(title: "hello_world\n").valid?` returns `true` on current `develop` and persists a title with a literal trailing newline, because `\Z` lets the `\n` slip through. `Label` only lowercases the title before validating (no `strip`), so nothing else catches this. This is a narrower/lower-severity variant of the #15415 bug (it only ever admits one specific trailing character, not an arbitrary prefix/suffix), but it's the same underlying mistake, independently verified against current source, not just pattern-matched from the diff. ## What changed - `lib/regex_helper.rb`: `UNICODE_CHARACTER_NUMBER_HYPHEN_UNDERSCORE` now ends in `\z` instead of `\Z`, with a comment explaining why. ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? Ran against a real local Rails env (Ruby 3.4.4, PostgreSQL 16, Redis): `bundle exec rspec spec/models/label_spec.rb` Added a regression test asserting `Label.new(title: "hello_world\n")` is invalid. Confirmed it fails against the pre-fix `\Z` regex and passes after switching to `\z`. All existing `label_spec.rb` examples (including the existing "foreign characters", "special characters", and "uppercase" title-validation cases) continue to pass unchanged. ## Checklist - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective - [x] New and existing unit tests pass locally with my changes 🤖 This fix was authored by an AI coding agent (Claude) working on behalf of Mithtech, an ERPNext/Frappe/Medusa.js implementation studio, as part of a deliberate effort to build a track record of verified upstream open-source contributions. Flagging this transparently per common courtesy — happy to answer any questions about the change, including how it was found (auditing for the same regex-anchor mistake class as #15415). Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,9 @@ module RegexHelper
|
||||
# the following regext needs atleast one character which should be
|
||||
# valid unicode letter, unicode number, underscore, hyphen
|
||||
# shouldn't start with a underscore or hyphen
|
||||
UNICODE_CHARACTER_NUMBER_HYPHEN_UNDERSCORE = Regexp.new('\A[\p{L}\p{N}]+[\p{L}\p{N}_-]+\Z')
|
||||
# \z (not \Z) anchors strictly to the end of the string -- \Z would also accept a single
|
||||
# trailing "\n", which would let a title like "hello_world\n" pass this validation.
|
||||
UNICODE_CHARACTER_NUMBER_HYPHEN_UNDERSCORE = Regexp.new('\A[\p{L}\p{N}]+[\p{L}\p{N}_-]+\z')
|
||||
# Regex to match mention markdown links and extract display names
|
||||
# Matches: [@display name](mention://user|team/id/url_encoded_name)
|
||||
# Captures: 1) @display name (including emojis), 2) url_encoded_name
|
||||
|
||||
@@ -26,6 +26,13 @@ RSpec.describe Label do
|
||||
expect(label.valid?).to be true
|
||||
end
|
||||
|
||||
it 'would not let you use a title with a trailing newline' do
|
||||
# Regression test: the format validator used to anchor on \Z instead of \z, and \Z tolerates
|
||||
# a single trailing newline, so 'hello_world' + "\n" incorrectly passed validation.
|
||||
label = FactoryBot.build(:label, title: "hello_world\n")
|
||||
expect(label.valid?).to be false
|
||||
end
|
||||
|
||||
it 'converts uppercase letters to lowercase' do
|
||||
label = FactoryBot.build(:label, title: 'Hello_World')
|
||||
expect(label.valid?).to be true
|
||||
|
||||
Reference in New Issue
Block a user