Rubyでの正規表現における行頭・行末の扱い


Railsでモデルのバリデーションを正規表現で、チェックしようとしたところエラーが起こったので備忘録としてメモしておきます。

環境

Ruby 2.5.1
Rails 5.2

エラーになった実装

user.rb
class User < ApplicationRecord
  validates :age, format: { with: /^[0-9]+$/, message: "は数値のみ入力可能です。"}
end

エラーの内容

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?

エラーの内容としては、^,$はセキュリティのリスクがあるため、\A,\zを使えと言われているようです。
^A
$z
上記の方法ではない場合、:multiline => trueオプションをつけることで脆弱性を含むコードでも、あえてエラーを発生させないとい方法もあります。

調べたところによると、Rails4以降ではセキュリティ対策として、正規表現が厳しくなったようです。

Rubyでは特定の頭と末尾を指定したマッチを行いたい場合は以下のように実装するのが良さそうです。
:multiline => trueオプションをつける方法もありますが、バリデーション処理の場合などは、特別な理由がない限りは、指定しないほうがいいのかなと感じました。

user.rb
class User < ApplicationRecord
  validates :age, format: { with: /\A[0-9]+\z/, message: "は数値のみ入力可能です。"}
end

一応Rubyの公式リファレンスでも以下のように定義されています。

^ 行頭にマッチします。行頭とは、文字列の先頭もしくは改行の次を 意味します。
$ 行末にマッチします。 行末とは文字列の末尾もしくは改行の手前を意味します。
\A 文字列の先頭にマッチします。
\z 文字列の末尾にマッチします。

参考文献

正規表現によるバリデーションでは ^ と $ ではなく \A と \z を使おう
Rails4では正規表現が厳しくなった。
Ruby 2.7.0 リファレンスマニュアル 正規表現