I'm setting up a user form in Rails that requires a first name and last name. I decided to use the 3rd to last regular expression from the this Ruby doc to ensure that they don't enter any numbers or special characters. Unfortunately when I return to the form I get this error:
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?.
I'm just beginning to learn RegEx so if there's a better way to write this validation I'm all ears.
Code:
validates :first_name, :last_name, length: {minimum: 2}, format: {with: /^([^\d\W]|[-])*$/, message: 'First Name/Last Name cannot have any numbers or special characters'}
The documentation you linked to states:
Note: use \A and \Z to match the start and end of the string, ^ and $ match the start/end of a line.
Since you don't need multiline support for names (i.e. newlines in the name should be regarded invalid), you can safely change this to:
/\A([^\d\W]|[-])*\Z/
See also this answer which explains the security risk a bit more.
You will need to use \A for start of line and \z for end of line instead of ^ and $ due to security reasons. So your regexp should be
/\A([^\d\W]|[-])*\z/
Related
I'm reading agile web development with rails 6.
In chapter 7, Task B: validation and unite testing
class Product < ApplicationRecord
validates :image_url, allow_blank: true, format: {
with: %r{\.(gif|jpg|png)\z}i,
}
what does the i mean in the end here?
It should mean that it's ending with .git or .jpg or .png
The i in your query tells the regex to match using a case insensitive match. There is nothing really unique to rails here so you may want to look into regexes in general to learn all the different terms you can use to modify your expression.
The expression %r{\.(gif|jpg|png)\z}i is equivalent to /\.(gif|jpg|png)\z/i
the \. means the period character
the | is an or as you stated
the \z is end of string with some caveats that you can read more about here: http://www.regular-expressions.info/anchors.html
and the i is incentive case matching
This means you would match 'test.jpg', 'test.JPg', 'test.JPG' or any permutation of those three characters in any case preceded by a period that occurs at the end of the string.
Here are the docs for regex formats in ruby specific:
https://ruby-doc.org/2.7.7/Regexp.html
And here is something where you can play with and learn regexes in general and try some expressions yourself:
https://regexr.com
short explain:
The "i" at the end of the regular expression is a modifier that makes the expression case-insensitive. This means that it will match both upper and lowercase letters in the image URL.
I'm finding a regular expression which adheres below rules.
Acceptance criteria: Password must contain a combination of letters, numbers, and at least a special character.`
Here is my Regex:
validates :password, presence: true,
format: { with: ^(?=[a-zA-Z0-9]*$)([^A-Za-z0-9])}
I am not all that great at regex, so any and all help is greatly appreciated!
You can use the following RegEx pattern
/^(?=.*\d)(?=.*([a-z]|[A-Z]))([\x20-\x7E]){8,}$/
Let's look at what it is doing:
(?=.*\d) shows that the string should contain atleast one integer.
(?=.*([a-z]|[A-Z])) shows that the string should contain atleast one alphabet either from downcase or upcase.
([\x20-\x7E]) shows that string can have special characters of ascii values 20 to 7E.
{8,} shows that string should be minimum of 8 characters long. While you have not mentioned it should be at least 8 characters long but it is good to have.
If you're unsure about the ASCII values, you can google it or you could use the following instead:
/^(?=.*\d)(?=.*([a-z]|[A-Z]))(?=.*[##$%^&+=]){8,}$/
As suggested in the comments, a better way can be:
/\A(?=.*\d)(?=.*([a-z]))(?=.*[##$%^&+=]){8,}\z/i
Here:
\A represents beginning of string.
\z represents end of string.
/i represents case in-sensitive mode.
P.S: I have not tested it yet. May be I'll test and update later if required.
I used brakeman for generating scanning reports in my application. It generated a Format Validation security warning with High Confidence in my model page:
Insufficient validation for 'name' using / +\w/. Use \A and \z as
anchors near line 54
This is the line in my model where I am facing error:
validates_format_of :name, :with => / +\w/, :message => "must be your first and last name."
If there is no space in the name field, I am showing above validation. How can show it \A and\z format?
Brakeman is recommending the use of \A and \z-anchors in your validation regex. They define where the match has to start at (\A) and end at (\z). Without them, the regex can simply match to any part of the name. Let's transform your regex to encompass the whole string:
/\A\w+ +\w+\z/
You can remove the + after the space if you only want to accept one space.
Using the normal regex line begin (^) and end ($) anchors is also not recommended, because it would be enough to have one line which matches, and all other lines could be invalid.
I want to validate a text string to make sure it is safe. I do not want to escape it, as I want to display it.
I have tried
validates :description, :format => { :with => /^[\-$ ?!."'\/,a-z0-9]+$/i
and it works in that it passes text with characters that are allowed and fails when characters not listed above are include.
But Brakeman issues a message that advocates replacing the ^ with \A and the $ with /z. However if I do this, the validator fails all tests.
It is not working cause you are using forward slash/ instead of back slash \. The /z means matching the characters / and z literally. It is \z or \Z And they mean as follows:
\z means the end of the string. Whereas
\Z means before an optional \n, and the end of the string.
So use the one which fits best with you!
I am having quite a weird error in my rails' unit test.
I have the following test which fails for some reason:
should_not allow_value('#!>::<>').for(:first_name)
and the following validation in my model:
validates_format_of :first_name, :last_name, with: (/[\w]*/), allow_blank: true
Any ideas as to why the test fails?
PS: Error seems to go away when I change the * to a + in the regex...But why!
The regex /[\w]*/ matches zero or more word characters in the input. Since there are no word characters in your test string, it happily validates it. /[\w]+/ needs at least one word character to have a match, and that's why it works with your test string.
I think you should use /^[\w]*$/ to specify that from the start of your string to the end, you only want word characters (special characters ^ and $ match the start and the end of input, respectively, in a regex). Note that this allows a blank input.