Biểu thức chính quy có xác thực trong RoR 4


83

Có mã sau:

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

Nó hoạt động, nhưng khi tôi cố gắng kiểm tra nó bằng cách sử dụng "kiểm tra rake", tôi sẽ nhận được thông báo sau:

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?

Nó có nghĩa là gì? Làm thế nào tôi có thể sửa chữa nó?


Bạn đã thử /\.(gif|jpg|png)$/ichưa? Có thể %r{}thêm nó $vào cuối.
Wukerplank,

@Wukerplank Tôi không nghĩ vậy. %r{\.(gif|jpg|png)$}i #=> /\.(gif|jpg|png)$/i, %r{\.(gif|jpg|png)}i #=> /\.(gif|jpg|png)/i.
sawa,

Có, nhưng nó đã không giúp đỡ
malcoauri

1
@wukerplank tại sao chúng ta lại đoán? trong ruby chúng tôi có irbđể giúp chúng tôi biết chắc chắn :)
mlibby

3
Bạn cần phải loại bỏ các $ sau png) mà chỉ ra rằng đây là mục cuối cùng và thay thế bằng \ z
Gary

Câu trả lời:


158

^$các neo Bắt đầu Dòng và Cuối Dòng . Trong khi \A\zcác neo bắt đầu vĩnh viễn của chuỗi và cuối chuỗi .
Thấy sự khác biệt:

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

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

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

Vì vậy, Rails đang nói với bạn, "Bạn có chắc chắn muốn sử dụng ^$? Bạn không muốn sử dụng \A\zthay thế?"

Có nhiều mối quan tâm về an ninh đường ray tạo ra cảnh báo này ở đây .


3
sửa chữa lên coloquialism không cần thiết
xaxxon

2
giải thích những gì nó đang hỏi nhưng không trả lời làm thế nào để khắc phục nó. Tôi cho rằng nếu bạn muốn sử dụng ^ và $ thì cách khắc phục là thêm: multiline => true vào đầu lớp?
isimmons

@isimmons Bằng cách thêm, :multiline => truebạn chỉ sửa được cảnh báo nói rằng Rails mà bạn biết bạn đang làm gì.
oldergod,

6
Câu trả lời là ở đó: đó là sử dụng \ A và \ z thay vì ^ và $ vì trong Ruby, ^ và $ chỉ khớp với một dòng mới không bắt đầu và kết thúc chuỗi, điều này cho phép khai thác javascript vượt qua bài kiểm tra.
JohnMerlino

31

Cảnh báo này xuất hiện vì quy tắc xác thực của bạn dễ bị chèn javascript.

Trong trường hợp của bạn \.(gif|jpg|png)$phù hợp cho đến cuối dòng. Vì vậy, quy tắc của bạn sẽ xác thực giá trị này pic.png\nalert(1);là đúng:

"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

Đọc các hạt:


Tốt nhất, ước gì chúng ta có thể biến điều này thành câu trả lời được chấp nhận.
mlibby

2

Vấn đề regexp không nằm trong devise, mà nằm trong config / initializers / devise.rb. Thay đổi:

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

đến:

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

1

Cảnh báo cho bạn biết rằng các chuỗi như sau sẽ vượt qua xác thực, nhưng nó có thể không phải là những gì bạn muốn:

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

Cả hai ^$đối sánh với điểm bắt đầu / kết thúc của bất kỳ dòng nào, không phải là đầu / cuối của chuỗi. \A\zkhớp với phần đầu và phần cuối của chuỗi đầy đủ, tương ứng.

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

Phần thứ hai của cảnh báo (“hoặc quên thêm tùy chọn: multiline => true”) cho bạn biết rằng nếu bạn thực sự muốn hành vi của ^$bạn có thể chỉ cần tắt tiếng cảnh báo chuyển :multilinetùy chọn.


Vậy bạn vượt qua :multilineđâu?
Pithikos

-1

Nếu Ruby muốn xem \zthay vì $ký hiệu biểu tượng, để bảo mật, bạn cần đưa nó cho anh ta, khi đó mã sẽ giống như sau:

validates :image_url, allow_blank: true, format: {with: %r{\.(gif|jpg|png)\z}i, message: 'URL must point to GIF, JPG, PNG.'}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.