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

## 内容
BrakemanのWarningと、調査中に出会ったRubyのメソッドの紹介


## Brakeman

### Command Injection

シェルコマンドを実行するrubyのメソッドに、パラメータを渡していると注意される。
> https://brakemanscanner.org/docs/warning_types/command_injection/

```
system(params[:hoge])
```

<br>

対処法としては、

```
system(コマンド, コマンドの引数)
```
とすればいいと[Ruby On Rails Guides](https://guides.rubyonrails.org/security.html#command-line-injection
)には書いてあるけど、例えば`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](https://docs.ruby-lang.org/ja/latest/method/Dir/s/mkdir.html)もある

## その他

### VSCODEで指定した行に移動する

`Ctrl + g`の後に行番号を入れる。