The provided regular expression is using multiline anchors (^ or $) - ruby-on-rails

I trying to write a Image validation format that makes sure url ends with either .png, .jpg or .gif .
class Product < ActiveRecord::Base
mount_uploader :image_url
validates :title, :presence => true,
:uniqueness => true
validates :image_url, :presence => true,
:format => {
:with => %r{\.(gif|jpg|png)$}i,
:message => 'must be a URL for GIF, JPG or PNG image.'
}
end
But when i start my server. seeing this:
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?

^ and $ are both line anchors. If a user were to pass in a string with http://www.foo.com/bar.png\nfoo_bar_baz!, then your regex is going say that the input is valid because it will match .png to the newline, which is not what you want.
Change your regex above to be %r{\.(gif|jpg|png)\z}i instead. The \z is an end of string anchor, which is what you want instead of the end of line anchor.
There are some great answers on another, very similar question: Difference between \A \z and ^ $ in Ruby regular expressions.

Related

Alpha-numeric regex from a ruby on rails 3 app not working in my ruby on rails 4 app

This is my model:
class Garment
include ActiveAttr::Model
#include ActiveModel::Validations
extend CarrierWave::Mount
attribute :title
mount_uploader :image, ImageUploader
alpha_numeric_regix = /\A[a-zA-Z0-9-_]\z/
validates :title, :presence => true,
:length => { :minimum => 5, :maximum => 30 },
:format => {
:with => alpha_numeric_regix,
:message => "must contain letters, dashes and underscores only"
}
How ever my actual form keeps telling me the validation has failed when I use purely letters and spaces e.g. VA Yellow Top
Rubular: http://rubular.com/r/ynd3DOWCxe
What could the problem be. In rubular using two letter "VA" fails validation as well.
What could be going on?
/\A[a-zA-Z0-9-_]\z/ + when I use purely letters and spaces - there is no space in your regex, should be
`/\A[a-zA-Z0-9\-_\ ]+\z/`

Regular expressions with validations in RoR 4

There is the following code:
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
It works, but when I try to test it using "rake test" I'll catch this 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?
What does it mean? How can I fix it?
^ and $ are Start of Line and End of Line anchors. While \A and \z are Permanent Start of String and End of String anchors.
See the difference:
string = "abcde\nzzzz"
# => "abcde\nzzzz"
/^abcde$/ === string
# => true
/\Aabcde\z/ === string
# => false
So Rails is telling you, "Are you sure you want to use ^ and $? Don't you want to use \A and \z instead?"
There is more on the rails security concern that generates this warning here.
This warning raises because your validation rule is vulnerable for javascript injection.
In your case \.(gif|jpg|png)$ matches till the end of the line. So your rule will validate this value pic.png\nalert(1); as true:
"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
Read the acticles:
http://caiustheory.com/validating-data-with-regular-expressions-in-ruby
http://guides.rubyonrails.org/security.html#regular-expressions
The problem regexp is not in devise, but rather lives in config/initializers/devise.rb. Change:
# Regex to use to validate the email address
config.email_regexp = /^([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})$/i
to:
# Regex to use to validate the email address
config.email_regexp = /\A([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})\Z/i
The warning is telling you that strings like the following will pass validation, but it is probably not what you want:
test = "image.gif\nthis is not an image"
re = /\.(gif|jpg|png)$/i
re.match(test) #=> #<MatchData ".gif" 1:"gif">
Both ^ and $ matches the start/end of any line, not the start/end of the string. \A and \z matches the start and the end of the full string, respectively.
re = /\.(gif|jpg|png)\z/i
re.match(test) #=> nil
The second part of the warning (“or forgot to add the :multiline => true option”) is telling you that if you actually want the behaviour of ^ and $ you can simply silence the warning passing the :multiline option.
If Ruby wants to see \z instead of the $ symbol sign, for security, you need to give it to him, then the code would look like this :
validates :image_url, allow_blank: true, format: {with: %r{\.(gif|jpg|png)\z}i, message: 'URL must point to GIF, JPG, PNG.'}

Simple rails format validation not firing

I'm building an app where users can create url slugs for their profile. To make sure the slugs are valid I've added a validation in the User model for slugs:
validates :slug, :uniqueness => true, :format => { :with => /[a-z]+/ }, :allow_nil => true, :allow_blank => true
However, validation seems to pass, regardless of what format the slug string is, for example:
u.slug = 'jlskdf .jc oi/slkdjfie\*asdf&(*&*ss%&'
=> "jlskdf .jc oi/slkdjfie\\*asdf&(*&*ss%&"
u.save
=> true
Apparently it doesn't matter what I change the regex to either, everything passes. I've tried this format as well:
validates_format_of :slug, :with => /[a-z]+/
which gives the same results. Anyone have any ideas of what could be happening?
Your regular expression isn't anchored, so the pattern matches as long as it contains at least one letter a-z. Anything else is valid. Add \A and \z to the beginning and end to prevent matching any substring within the larger input.
:with => /\A[a-z]+\z/

Rails custom validation based on a regex?

I have the following regex that I use in my routes.rb for /type-in-something-here
# A-Z, a-z, 0-9, _ in the middle but never starting or ending in a _
# At least 5, no more than 500 characters
In the routes this works well as:
match ':uuid' => 'room#show', :constraints => { :uuid => /[A-Za-z\d]([-\w]{,498}[A-Za-z\d])?/ }
I want to have this also as a validation so invalid records aren't created. So I added the following to room.rb:
validates_format_of :uuid, :with => /[A-Za-z\d]([-\w]{,498}[A-Za-z\d])?/i, :message => "Invalid! Alphanumerics only."
But this validates_format_of isn't working, and instead of adding an error it's allow the record to save.
Any ideas what's wrong?
Thanks
For validation purposes, remember to add the beginning and end of string markers \A and \Z:
validates_format_of :uuid, :with => /\A[A-Za-z\d]([-\w]{,498}[A-Za-z\d])?\Z/i
Otherwise your regex will happily match any string that contains at least a letter or a digit. For some reason Rails implicitly adds the boundaries in the routes. (Probably because it embeds the regex inside a larger one to match the entire URL, with explicit checks for / and the end of the URL.)
using something like this
validates :uuid, :format => {:with => /[A-Za-z\d]([-\w]{,498}[A-Za-z\d])?/i},
:message => "your message"
For more check this
validates :name, format: { with: /\A[a-zA-Z]+\z/,
message: "Only letters are allowed" }

Validate: Only letters, numbers and -

I would like to validate my users, so they can only use a-z and - in their username.
validates_format_of :username, :with => /[a-z]/
However this rule also allows spaces ._#
Username should use only letters, numbers, spaces, and .-_# please.
Any ideas?
Best regards.
Asbjørn Morell
You may need to say the whole string must match:
validates_format_of :username, :with => /^[-a-z]+$/
You may also need to replace ^ with \A and $ with \Z, if you don't want to match a newline at the start/end. (thanks to BaroqueBobcat)
Appending an i will cause it to match in a case-insensitive manner. (thanks to Omar Qureshi).
(I also originally left off the +: thanks to Chuck)
More complex solution but reusable and with more fine grained error messaging.
Custom validator:
app/validators/username_convention_validator.rb
class UsernameConventionValidator < ActiveModel::EachValidator
def validate_each(record, field, value)
unless value.blank?
record.errors[field] << "is not alphanumeric (letters, numbers, underscores or periods)" unless value =~ /^[[:alnum:]._-]+$/
record.errors[field] << "should start with a letter" unless value[0] =~ /[A-Za-z]/
record.errors[field] << "contains illegal characters" unless value.ascii_only?
end
end
end
(Notice it does allow ' . - _ ' and doesnt allow non ascii, for completeness sake)
Usage:
app/models/user.rb
validates :name,
:presence => true,
:uniqueness => true,
:username_convention => true
The [] may contain several "rules" so [a-z0-9] gives lowercase letters and numbers
the special character - must go at the start of the rule
Does
[-a-z0-9#_.]
give the effect you want?
validates_format_of :username, :with => /^[\w\-#]*$/
Note the *, which means '0 or more'
Simply change the regular expression to match all characters your specification states (\w covers all alphanumeric characters -- letters and numbers -- and an underscore).
validates_format_of :username, :with => /[\w \.\-#]+/
Validation to allow letters and whole numbers only:
/\A[a-zA-Z0-9]+\z/

Resources