Jest następujący kod:
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
Działa, ale kiedy spróbuję go przetestować za pomocą „testu rake”, wyłapię tę wiadomość:
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?
Co to znaczy? Jak mogę to naprawić?
ruby-on-rails
ruby
activerecord
malcoauri
źródło
źródło
/\.(gif|jpg|png)$/i
? Może na końcu%r{}
dodaje swój własny$
.%r{\.(gif|jpg|png)$}i #=> /\.(gif|jpg|png)$/i
,%r{\.(gif|jpg|png)}i #=> /\.(gif|jpg|png)/i
.irb
nam pomóc wiedzieć na pewno :)Odpowiedzi:
^
i$
to start z linii i End Of Line kotwic. Choć\A
i\z
są trwałe start String i koniec sznurka kotwic.Zobacz różnicę:
string = "abcde\nzzzz" # => "abcde\nzzzz" /^abcde$/ === string # => true /\Aabcde\z/ === string # => false
Więc Rails mówi ci: "Czy na pewno chcesz użyć
^
i$
? Nie chcesz użyć zamiast tego\A
i\z
?"Jest bardziej na obawy zabezpieczeń szyn, który generuje to ostrzeżenie tutaj .
źródło
:multiline => true
, naprawiasz tylko ostrzeżenie, że Railsy wiesz, co robisz.To ostrzeżenie pojawia się, ponieważ reguła weryfikacji jest podatna na wstrzyknięcie kodu JavaScript.
W twoim przypadku
\.(gif|jpg|png)$
mecze do końca linii. Twoja reguła potwierdzi tę wartośćpic.png\nalert(1);
jako prawdziwą:"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
Przeczytaj akty:
źródło
Problem regexp nie jest wymyślony, ale raczej żyje w config / initializers / devise.rb. Zmiana:
# Regex to use to validate the email address config.email_regexp = /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i
do:
# Regex to use to validate the email address config.email_regexp = /\A([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})\Z/i
źródło
Ostrzeżenie mówi ci, że łańcuchy takie jak poniższe przejdą walidację, ale prawdopodobnie nie jest to to, czego chcesz:
test = "image.gif\nthis is not an image" re = /\.(gif|jpg|png)$/i re.match(test) #=> #<MatchData ".gif" 1:"gif">
Oba
^
i$
dopasowuje początek / koniec dowolnego wiersza, a nie początek / koniec ciągu.\A
i\z
dopasowuje odpowiednio początek i koniec pełnego ciągu.re = /\.(gif|jpg|png)\z/i re.match(test) #=> nil
Druga część ostrzeżenia („lub zapomniałeś dodać: multiline => opcja true”) mówi ci, że jeśli rzeczywiście chcesz zachowanie
^
i$
możesz po prostu wyciszyć ostrzeżenie, przekazując tę:multiline
opcję.źródło
:multiline
?Jeśli Ruby chce widzieć
\z
zamiast$
znaku symbolu, ze względów bezpieczeństwa, musisz mu go podać, wtedy kod wyglądałby tak:validates :image_url, allow_blank: true, format: {with: %r{\.(gif|jpg|png)\z}i, message: 'URL must point to GIF, JPG, PNG.'}
źródło