Expresiones regulares con validaciones en RoR 4

83

Existe el siguiente código:

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

Funciona, pero cuando intento probarlo usando "rake test", captaré este mensaje:

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é significa eso? ¿Cómo puedo arreglarlo?

malcoauri
fuente
¿Usted ha intentado /\.(gif|jpg|png)$/i? Quizás %r{}agregue el suyo $al final.
Wukerplank
@Wukerplank No lo creo. %r{\.(gif|jpg|png)$}i #=> /\.(gif|jpg|png)$/i, %r{\.(gif|jpg|png)}i #=> /\.(gif|jpg|png)/i.
sawa
Sí, pero no ayudó
malcoauri
1
@wukerplank, ¿por qué estamos adivinando? en ruby ​​tenemos irbque ayudarnos a saberlo con certeza :)
mlibby
3
Debe eliminar $ después de png) que indica que este es el último elemento y reemplazarlo con \ z
Gary

Respuestas:

158

^y $son anclas de inicio de línea y final de línea . Mientras \Ay \zson anclajes permanentes de inicio de cadena y final de cadena .
Ver la diferencia:

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

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

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

Entonces Rails te está diciendo: "¿Estás seguro de que quieres usar ^y $? ¿No quieres usar \Ay en su \zlugar?"

Hay más preocupación por la seguridad de los rieles que genera esta advertencia aquí .

dios mayor
fuente
3
arreglando el coloquialismo innecesario
xaxxon
2
explica lo que pregunta pero no responde cómo solucionarlo. Supongo que si desea usar ^ y $, la forma de solucionarlo es agregar: multiline => true en la parte superior de la clase.
isimmons
@isimmons Al agregar :multiline => trueque solo corrige la advertencia que dice Rails, sabe lo que está haciendo.
dios mayor
6
La respuesta está ahí: es usar \ A y \ z en lugar de ^ y $ porque en Ruby, ^ y $ coinciden solo con una nueva línea, no el comienzo y el final de la cadena, lo que permite que un exploit de javascript pase la prueba.
JohnMerlino
31

Esta advertencia surge porque su regla de validación es vulnerable a la inyección de JavaScript.

En su caso, \.(gif|jpg|png)$coincide hasta el final de la línea. Entonces su regla validará este valor pic.png\nalert(1);como verdadero:

"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

Lea los artículos:

viejo
fuente
Lo mejor del grupo, ojalá pudiéramos hacer de esta la respuesta aceptada.
mlibby
2

El problema regexp no está en devise, sino que vive en config / initializers / devise.rb. Cambio:

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

a:

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

La advertencia le dice que cadenas como las siguientes pasarán la validación, pero probablemente no sea lo que desea:

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

Ambos ^y $coincide con el inicio / final de cualquier línea, no con el inicio / final de la cadena. \Ay \zcoincide con el inicio y el final de la cadena completa, respectivamente.

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

La segunda parte de la advertencia ("u olvidé agregar la opción: multiline => true") le dice que si realmente desea el comportamiento de ^y $puede simplemente silenciar la advertencia pasando la :multilineopción.

yonosoytu
fuente
Entonces, ¿por dónde pasas :multiline?
Pithikos
-1

Si Ruby quiere ver en \zlugar del $signo del símbolo, por seguridad, debe dárselo, entonces el código se vería así:

validates :image_url, allow_blank: true, format: {with: %r{\.(gif|jpg|png)\z}i, message: 'URL must point to GIF, JPG, PNG.'}
max
fuente