Регулярные выражения с проверками в RoR 4


есть следующий код:

class Product < ActiveRecord::Base
  validates :title, :description, :image_url, presence: true
  validates :price, numericality: {greater_than_or_equal_to: 0.01}
  validates :title, uniqueness: true
  validates :image_url, allow_blank: true, format: {
      with: %r{.(gif|jpg|png)$}i,
      message: 'URL must point to GIT/JPG/PNG pictures'
  }
end

это работает, но когда я пытаюсь проверить его с помощью "rake test" я поймаю это сообщение:

rake aborted!
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?

что это значит? Как я могу это исправить?

5 78

5 ответов:

^ и $ старт в строке и конец в строке якоря. В то время как \A и \z постоянный старт строки и конец строки якоря.
Смотрите разницу:

string = "abcde\nzzzz"
# => "abcde\nzzzz"

/^abcde$/ === string
# => true

/\Aabcde\z/ === string
# => false

Итак, Rails говорит вам: "вы уверены, что хотите использовать ^ и $? Вы не хотите использовать \A и \z вместо этого?"

есть еще на рельсах озабоченность безопасностью, которая генерирует это предупреждение здесь.

это предупреждение возникает, потому что ваше правило проверки уязвимо для инъекции javascript.

в вашем случае \.(gif|jpg|png)$ матчи до конца строки. Поэтому ваше правило будет проверять это значение pic.png\nalert(1); а так:

"test.png\n<script>alert(1)</script>" === /\.(gif|jpg|png)$/i
# => true

"test.png\n<script>alert(1)</script>" === /\.(gif|jpg|png)\z/i
# => false

читать статей:

проблема regexp не в devise, а скорее живет в config/initializers/devise.рубидий. Изменение:

# Regex to use to validate the email address
config.email_regexp = /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i

to:

# Regex to use to validate the email address
  config.email_regexp = /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\Z/i

предупреждение говорит вам, что строки, подобные следующим, пройдут проверку, но это, вероятно, не то, что вы хотите:

test = "image.gif\nthis is not an image"
re = /\.(gif|jpg|png)$/i
re.match(test) #=> #<MatchData ".gif" 1:"gif">

и ^ и $ соответствует началу / концу любой строки, а не началу/концу строки. \A и \z соответствует началу и концу полной строки, соответственно.

re = /\.(gif|jpg|png)\z/i
re.match(test) #=> nil

вторая часть предупреждения ("или забыл добавить: multiline => true option") говорит вам, что если вы действительно хотите поведение ^ и $ вы можете просто заставить замолчать предупреждение, передавая .

Если Руби хочет видеть \z вместо $ символ знак, для безопасности, вам нужно дать его ему, то код будет выглядеть так:

validates :image_url, allow_blank: true, format: {with: %r{\.(gif|jpg|png)\z}i, message: 'URL must point to GIF, JPG, PNG.'}