I'm trying to write a regular expression in Ruby (Rails) so that a username's characters only contains numbers and letters (also no spaces).
I have this regex, /^[a-zA-Z0-9]+$/
, but it doesn't seem to be working and I get an error in Rails that says "The provided regular expression is using multiline anchors (^ or $), which may present a security risk. Did you mean to use \A and \z, or forgot to add the :multiline => true option?"
My full code for this implementation in my user.rb model is:
class User < ActiveRecord::Base
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_USERNAME_REGEX = /^[a-zA-Z0-9]+$/
validates :username, presence: true, length: { maximum: 20 },
format: { with: VALID_USERNAME_REGEX },
uniqueness: { case_sensitive: false }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: 6 }
end
What am I doing wrong and how I can fix this regex so that it only is valid for numbers and letters and no spaces? Thanks.
Short answer: use /\A[a-zA-Z0-9]+\z/
instead (as VALID_EMAIL_REGEX
is using).
Long answer: the ^
and $
anchors will match the beginning and end of a line in a string. That means that if your string consists of multiple lines of alphanumeric characters they will match:
/^[a-zA-Z0-9]+$/ =~ "Ana\nBob\nClara\nDaniel" #=> 0 (matches)
The \A
and \z
on the other hand will match the beginning and end of a string, hence it will prevent a possible attack by a user sending a multiline string (like in the previous example).
/\A[a-zA-Z0-9]+\z/ =~ "Ana\nBob\nClara\nDaniel" #=> nil (doesn't match)
/\A[a-zA-Z0-9]+\z/ =~ "Erika" #=> 0 (matches)
All you have to do is follow the error message. Replace ^
(start of line anchor) with \A
(start of string anchor), and $
(end of line anchor) with \z
(end of string anchor). Other than that, your regex works as is.
\A[a-zA-Z0-9]+\z
Rails has this security concern because unlike some languages, ^
and $
only match the beginning/end of a single line, rather than the entire string.
This illustrates an example of this possible exploit:
str = "malicious_code()\naValidUsername"
str.match(/^[a-zA-Z0-9]+$/) # => #<MatchData "aValidUsername">
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With