内容
BrakemanのWarningと、調査中に出会ったRubyのメソッドの紹介
Brakeman
Command Injection
シェルコマンドを実行するrubyのメソッドに、パラメータを渡していると注意される。
https://brakemanscanner.org/docs/warning_types/command_injection/
system(params[:hoge])
対処法としては、
system(コマンド, コマンドの引数)
とすればいいとRuby On Rails Guidesには書いてあるけど、例えばsystem("rails runner")
に引数を渡そうとすると、上記の形ではうまくいかない。
pry(main)> system("rails runner puts 'hoge'")
=> true
pry(main)> system("rails runner", "puts 'hoge'")
=> nil
メソッド
Kernel.#system
引数を外部コマンドとして実行して、成功した時に真を返します。
https://docs.ruby-lang.org/ja/latest/method/Kernel/m/system.html
pry(main)> system("echo 'hoge'")
hoge
=> true
pry(main)> system("mkdir hoge/hoge")
mkdir: hoge: No such file or directory
=> false
## rails s とかもできる
pry(main)> system("rails s")
=> Booting Puma
=> Rails 5.2.2 application starting in development
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.12.2 (ruby 2.5.7-p206), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop
ちなみにoptionのexception
はrubyが2.6以上じゃないと使えないらしい。
pry(main)> system("echo 'hoge'", exception: true)
ArgumentError: wrong exec option symbol: exception
Kernel.#spawn
引数を外部コマンドとして実行しますが、生成した子プロセスの終了を待ち合わせません。生成した子プロセスのプロセスIDを返します。
https://docs.ruby-lang.org/ja/latest/method/Kernel/m/spawn.html
pry(main)> spawn("echo 'hoge'")
hoge
=> 2925
Open3.#capture3
cmd(引数)で指定されたコマンドを実行し、そのプロセスの標準出力と標準エラー、プロセスの終了ステータスを表すオブジェクトを返します。
https://docs.ruby-lang.org/ja/latest/method/Open3/m/capture3.html
## requireが必要
pry(main)> require "open3"
=> true
pry(main)> Open3.capture3("echo 'hoge'")
=> ["hoge\n", "", #<Process::Status: pid 2933 exit 0>]
Dir.mkdir
一時ディレクトリを作成します。
https://docs.ruby-lang.org/ja/latest/method/Dir/s/mktmpdir.html
pry(main)> Dir.mktmpdir do |filepath|
end
"/var/folders/6b/l0fppqp93rj892rb0fkx7tsc0000gq/T/d20200422-2910-1gt32e1"
=> "/var/folders/6b/l0fppqp93rj892rb0fkx7tsc0000gq/T/d20200422-2910-1gt32e1"
pry(main)> Dir.mktmpdir
=> "/var/folders/6b/l0fppqp93rj892rb0fkx7tsc0000gq/T/d20200422-2910-1u1nilk"
ブロックを渡すと、
ブロックが与えられた場合は、ブロックの評価が終わると作成された一時ディレクトリやその配下にあったファイルを FileUtils.#remove_entry を用いて削除し、ブロックの値をかえします。
文字列だと、
ブロックが与えられなかった場合は、作成した一時ディレクトリのパスを返します。この場合、このメソッドは作成した一時ディレクトリを削除しません。
ちなみに、第二引数を指定するとそのディレクトリ以下に、指定しないとDir.tmpdir
以下にディレクトリが作成される模様。
pry(main)> Dir.mktmpdir(nil, "/var/tmp") do |file|
pry(main)* p file
pry(main)* end
"/var/tmp/d20200422-2910-d47k8"
=> "/var/tmp/d20200422-2910-d47k8"
## 存在しないディレクトリだとエラー
pry(main)> Dir.mktmpdir(nil, "/hoge/tmp") do |file|
pry(main)* p file
pry(main)* end
Errno::ENOENT: No such file or directory @ dir_s_mkdir - /hoge/tmp/d20200422-2910-1edebg4
Dir.tmpdir
テンポラリファイルを作成するのに使うディレクトリ(テンポラリディレクトリ)の絶対パスを文字列として返します。
https://docs.ruby-lang.org/ja/latest/method/Dir/s/tmpdir.html
pry(main)> Dir.tmpdir
=> "/var/folders/6b/l0fppqp93rj892rb0fkx7tsc0000gq/T"
もちろんDir.mkdirもある
その他
VSCODEで指定した行に移動する
Ctrl + g
の後に行番号を入れる。