LoginSignup
1
0

More than 3 years have passed since last update.

学んだこと備忘録 2020/04/21

Last updated at Posted at 2020-04-22

内容

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以上じゃないと使えないらしい。

https://techracho.bpsinc.jp/hachi8833/2018_08_24/60356

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の後に行番号を入れる。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0