web-dev-qa-db-fra.com

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 quand j'essaye de le tester en utilisant le "test de râteau", je vais attraper 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 ça veut dire? Comment puis-je le réparer?

82
malcoauri

^ et $ sont les ancres Début de la Ligne et Fin de la Ligne . Tandis que \A et \z sont des ancres Début permanent de chaîne et Fin de chaîne .
Regarde la différence:

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

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

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

Donc Rails vous dit: "Êtes-vous sûr de vouloir utiliser ^ et $? Ne voulez-vous pas utiliser \A et \z au lieu?"

Il y a plus sur le Rails problème de sécurité qui génère cet avertissement ici .

151
oldergod

Cet avertissement s'affiche car votre règle de validation est vulnérable à l'injection javascript.

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

"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 acticules:

30
ole

Le regexp de problème n'est pas dans devise, mais vit plutôt dans config/initializers/devise.rb. Changement:

# 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
2
mcr

L'avertissement vous indique que des chaînes comme les suivantes 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">

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

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

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

1
yonosoytu