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


83

Вот такой код:

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?

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


Вы пробовали /\.(gif|jpg|png)$/i? Может быть %r{}, $в конце добавит свое .
Wukerplank

@Wukerplank Я так не думаю. %r{\.(gif|jpg|png)$}i #=> /\.(gif|jpg|png)$/i, %r{\.(gif|jpg|png)}i #=> /\.(gif|jpg|png)/i.
sawa

Да, но это не помогло
Малкоаури

1
@wukerplank, почему мы гадаем? в рубине мы должны irbпомочь нам узнать наверняка :)
mlibby

3
Вам необходимо удалить символ $ после png), который указывает, что это последний элемент, и заменить его на \ z
Гэри

Ответы:


158

^и $является Стартом Лайна и Конца Строки якорей. Хотя \Aи \zявляются постоянным Началом Строки и Конец струнных якорей.
Увидеть разницу:

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

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

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

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

Есть еще одна проблема безопасности, которая вызывает это предупреждение здесь .


3
исправление ненужного колоквиализма
xaxxon

2
объясняет, о чем спрашивает, но не отвечает, как это исправить. Я полагаю, если вы хотите использовать ^ и $, способ исправить это - добавить: multiline => true в начало класса?
isimmons

@isimmons Добавляя, :multiline => trueвы исправляете только предупреждение о том, что Rails вы знаете, что делаете.
oldgod

6
Ответ есть: нужно использовать \ A и \ z, а не ^ и $, потому что в Ruby ^ и $ соответствуют только новой строке, а не началу и концу строки, что позволяет эксплойту javascript пройти тест.
JohnMerlino

31

Это предупреждение возникает, потому что ваше правило проверки уязвимо для инъекции 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

Прочтите статьи:


Лучший из всех, хотел бы мы сделать это принятым ответом.
mlibby

2

Проблема с регулярным выражением не в разработке, а скорее находится в config / initializers / devise.rb. Изменить:

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

кому:

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

1

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

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») сообщает вам, что если вы действительно хотите, чтобы поведение ^и $вы могли просто отключить предупреждение, передав эту :multilineопцию.


Итак, где вы проходите :multiline?
Pithikos

-1

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

validates :image_url, allow_blank: true, format: {with: %r{\.(gif|jpg|png)\z}i, message: 'URL must point to GIF, JPG, PNG.'}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.