3

I am following along with the book Beginning Rails 4.

There appears to be a mistake in Chapter 6 related to this:

"A common pitfall in Ruby's regular expressions is to match the string's beginning and end by ^ and $, instead of \A and \z."

Which I saw here: http://guides.rubyonrails.org/security.html#regular-expressions

In particular, there is a User model with an email attribute, the format of which the book says to validate with:

validates_format_of :email, :with => /^[^@][\w.-]+@[\w.-]+[.][a-z]{2,4}$/i

The format validator raises an exception:

ArgumentError: 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?

I just want to make sure: this is precisely the case where using ^ and $ is a security threat, right?

If so, I can substitute ^ and $ with \A and \z. But how would I use the :multiline => true option in this case?

Arvind
  • 2,671
  • 1
  • 18
  • 32
evianpring
  • 3,316
  • 1
  • 25
  • 54
  • 1
    have you seen this http://stackoverflow.com/questions/17759735/regular-expressions-with-validations-in-ror-4 – Arvind Sep 26 '15 at 06:24

2 Answers2

1

It's precisely the security error you pointed to. It's insecure to use ^ and $ in this context. This warning appeared in Rails 4. If you are using Rails 3 your validation will never complain about this. But security risks is the same in Rails 3 as well.

:multiline => true parameter is required if you actually need to compare beginning and end of the line, as opposed to comparing beginning and end of the string. It was introduced due to frequent misuse of ^ and $ instead \A and \z.

dimakura
  • 7,575
  • 17
  • 36
  • What is the exact line of code that would be used in my example, with the :multiline parameter? – evianpring Sep 26 '15 at 22:57
  • @evianpring you can silent Rails with `validates_format_of :email, :with => /^[^@][\w.-]+@[\w.-]+[.][a-z]{2,4}$/i, multiline: true`, but you should not. You should use `/\A[^@][\w.-]+@[\w.-]+[.][a-z]{2,4}\z/i` instead. I doubt you will even encounter the case when you need `multiline`. – dimakura Sep 27 '15 at 05:39
1
  • ^ is start of line
  • \A is start of string

If you will use /^[^@][\w.-]+@[\w.-]+[.][a-z]{2,4}$/i anybody can send to you next string

"some sql injection or something like that

valid@email.com"

and it will pass your regex test.

So never use ^ if you want to check start of string.

6.6 Regular Expressions

Since this is a frequent mistake, the format validator (validates_format_of) now raises an exception if the provided regular expression starts with ^ or ends with $. If you do need to use ^ and $ instead of \A and \z (which is rare), you can set the :multiline option to true, like so:

# content should include a line "Meanwhile" anywhere in the string
validates :content, format: { with: /^Meanwhile$/, multiline: true }
Arsen
  • 10,815
  • 2
  • 34
  • 46