83 votes

Expressions régulières avec validations dans RoR 4

Il y a le code suivant :

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

Cela fonctionne, mais lorsque j'essaie de le tester en utilisant "rake test", je reçois ce message :

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?

Qu'est-ce que cela signifie ? Comment puis-je le réparer ?

156voto

oldergod Points 6979

^ y $ sont Start de la ligne et fin de la ligne ancres. Alors que \A y \z sont permanents Début de String et fin de String ancres.
Voyez la différence :

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

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

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

Donc Rails te dit, "Es-tu sûr que tu veux utiliser ^ y $ ? Ne voulez-vous pas utiliser \A y \z à la place ?"

Il y a plus sur le problème de sécurité des rails qui génère cet avertissement aquí .

31voto

ole Points 1832

Cet avertissement apparaît parce que votre règle de validation est vulnérable à l'injection de javascript.

Dans votre cas \.(gif|jpg|png)$ jusqu'à la fin de la ligne. Ainsi, votre règle validera cette valeur pic.png\nalert(1); comme vrai :

"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

Lisez les articles :

2voto

mcr Points 2857

La regexp problématique ne se trouve pas dans devise, mais plutôt dans config/initializers/devise.rb. Changez :

# 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

1voto

yonosoytu Points 2103

L'avertissement vous indique que des chaînes comme celles qui suivent passeront la validation, mais ce n'est probablement pas ce que vous voulez :

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

Les deux sites ^ y $ correspond au début/à la fin de n'importe quelle ligne, et non au début/à la fin de la chaîne. \A y \z correspond au début et à la fin de la chaîne complète, respectivement.

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

La deuxième partie de l'avertissement ("ou a oublié d'ajouter l'option :multiline => true") vous indique que si vous souhaitez réellement obtenir le comportement de la commande ^ y $ vous pouvez simplement faire taire l'avertissement en passant la commande :multiline option.

0voto

riliwanrabo Points 70

En utilisant %r{} ajouter son propre signe de dollar '$' à la fin, être d'accord avec @wukerplank retirer le $ here : %r{\.(gif|jpg|png) $ } et ré-exécutez votre test

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X