Trying to write REGEX to verify username in Rails

I am trying to write a regular expression in Ruby (Rails), so that username characters only contain numbers and letters (also no spaces).

I have this regular expression, /^[a-zA-Z0-9]+$/ , but it doesn’t seem to work, and I get an error message in Rails that says: "The provided regular expression uses multi-line anchors (^ or $), which could be a security risk. Did you mean to use \ A and \ z or forgot to add: multiline => true option? "

My complete 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+\-.] +@ [az\d\-.]+\.[az]+\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 can I fix this regular expression so that it is valid only for numbers and letters and spaces? Thanks.

+5
source share
2 answers

Short answer: use /\A[a-zA-Z0-9]+\z/ instead (using VALID_EMAIL_REGEX ).

Long answer: ^ and $ bindings will match the beginning and end of the line in line. This means that if your string consists of several strings of alphanumeric characters, they will correspond to:

 /^[a-zA-Z0-9]+$/ =~ "Ana\nBob\nClara\nDaniel" #=> 0 (matches) 

On the other hand, \A and \z will match the beginning and end of a line , so this will prevent a possible attack by the user sending the multiline string (for example, 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) 
+9
source

All you have to do is follow the error message. Replace ^ (beginning of line binding) with \A (beginning of line binding) and $ (end of line of binding) with \z (end of line binding). Other than that, your regular expression works as it is.

 \A[a-zA-Z0-9]+\z 

Rails has this security issue because, unlike some languages, ^ and $ correspond only to the beginning / end of one line, and not the entire line.

This illustrates an example of this possible use:

 str = "malicious_code()\naValidUsername" str.match(/^[a-zA-Z0-9]+$/) # => #<MatchData "aValidUsername"> 
+2
source

Source: https://habr.com/ru/post/1206763/


All Articles