👻

【Ruby 4.0 Advent Calender】Kernel.#open で '|コマンド' の機能が削除された【5日目】

に公開
2025/12/06

Ruby 4.0 Advent Calender 5日目の記事です。

これはなに

今年 2025年12月25日にリリースされる予定の Ruby 4.0 の新機能や変更点などを1つずつ紹介していく Advent Calender になります。
基本的には NEWS に載っている機能を紹介すると思うんですがここにない機能についても書くかもしれません。
また、記事を書いてる時点ではまだ Ruby 4.0 はリリースされる前なので Ruby 4.0 がリリースされた時点で機能が変わっている 可能性があるかもしれないので注意してください。
記事のまとめは ここを参照 してください。

Kernel.#open から | のサポートが削除される

Kernel.#open は通常ファイルをオープンして読み込むためのメソッドです。

# test.txt を開いてファイルの中身を読み込んでくる
puts open('./test.txt').readlines
__END__
output:
homu
mami
mado

通常は上記のようにファイルを読み込む用途で利用することが一般的だと思うんですがこの open に |{任意の外部コマンド} を渡すとそのコマンドを実行することができます。

# mkdir hoge が外部コマンドとして実行される
open("|mkdir hoge")

通常はこのような利用の方をすることはないと思うんですがユーザの任意の入力値を Kernel.#open に渡すようなコードを書いてしまうと脆弱性につながる可能性があります。

# なにか URL のパラメータを受け取り open するようなコードがある場合に
# http://127.0.0.1:3000/?url=|date%3E%3E/tmp/rce1.txt
# のようなリクエストが飛んでくると `date>>/tmp/rce1.txt` のコマンドが意図せず実行されてしまう
open(params[:path_or_url])

参照: Ruby Vulnerabilities: Exploiting Open, Send, and… | Bishop Fox

このような脆弱性に関する課題があり Ruby 4.0 ではこの機能が削除されました。

open("|mkdir hoge")
# Ruby 3.4 => no error
# Ruby 4.0 => error: No such file or directory @ rb_sysopen - |mkdir hoge (Errno::ENOENT)

また Kernerl.#open 以外でも以下のメソッドでもこの挙動は削除されました。

  • URI.open
  • IO.binread
  • IO.foreach
  • IO.readlines
  • IO.read
  • IO.write

ちなみに Ruby 3.3 の時点で -w をつけておけば次のように警告がでるようになっていました。

open("|mkdir hoge")
# Ruby 3.3 -w なし => no warning
# Ruby 3.3 -w あり => warning: Calling Kernel#open with a leading '|' is deprecated and will be removed in Ruby 4.0; use IO.popen instead

一応 |コマンド が利用できなくなるので非互換な変更になるのでそういう意味でまずは警告を出すようにして移行を促していた形になります。

関連

GitHubで編集を提案

Discussion