Регулярні вирази з підтвердженнями в 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 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

Так, але це не допомогло
malcoauri

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, що ви знаєте, що робите.
старшийгод

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

Проблема регулярного виразу не у devise, а навпаки, живе в 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?
Пітікос

-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.