Edited at

CircleCIでの環境変数のセキュリティ (設定画面で設定した環境変数)


確認したいこと

確認したいことは、「CircleCIの歯車アイコン(⚙)で設定した環境変数がどういうときにリークする可能性があるか」です。

サービスのトークンなどを環境変数として設定する用途などで利用すると思いますが、トークンの流出が怖いのでどういうときに起こりうるかしっかりと確認したいと思います。


検証方法


  • CircleCI 2.0を使います。

  • コンテナベースのビルドで試しました。



    • docker: [image: ...]を使っていてmachine: trueは使ってません。


    • circleci/node:10イメージを使いました。




  • MY_SECRET1This is secret message!を設定しました。

  • 環境変数の取得方法は以下の3つを試しました。


    • echo $MY_SECRET1


    • envコマンド

    • node -e 'console.log(process.env)'




console.log(process.env)を使った理由

console.log(process.env)を使うと環境変数名と値がkey-valueのオブジェクトとして出力できます。

{ CIRCLE_NODE_INDEX: '0',

YARN_VERSION: '1.13.0',
CIRCLE_COMPARE_URL: '',
...省略...
}

console.log(process.env)みたいに言語の機能を使ったのは、以下のような可能性を排除したかったからです。



  • $MYSECRET1が含まれていたら、コマンド動かさないとか、


  • envコマンドに細工しているとか、

  • 出力に秘密の環境変数の値が含まれていたら消すみたいなフィルタリング

process.envのオブジェクトにkey-valueとして含まれていなかったら、おそらくCI動く前から環境変数をセットしないで動かしている内部実装なのかなと判断できると思いました。

Node.jsを使った意味は特にないです。


結果

GitHubアカウントは2つ用意して行いました。

どちらのアカウントで起こったことなのかを分かりやすくするために名前つけます。


  • オリジナルリポジトリのアカウントをauthorのAさん

  • フォークしてコントリビュートする人をcontributorのCさん
    とします。


CさんがforkしたリポジトリをCさんのCircleCIでビルドした場合

以下のような結果で、forkした場合にビルドされてもリークはしなくて安心です。(確かこれは公式ドキュメントに書いてあった気がします)


  • echo $MY_SECRET1`: 何も表示されない


  • envコマンド: MY_SECRET1が含まれていない


  • node -e 'console.log(process.env)' : MY_SECRET1が含まれていない

(この挙動を見る限り、MY_SECRET1が完璧にセットされない状態で、CIが動いている感じがします。)


CさんがforkしたリポジトリからAさんにプルリクエストした場合

この場合、CさんがCircleCIのアカウントを持っていれば、passしたところに✔がついたりして、CircleCIが走ります。ただ持っていなければCircleCIが動かないため上記の結果と同じになります。


Cさんのプルリクエストをマージしたとき

authorのAさんが緑色の[Merge]ボタンを押してマージすると、環境変数はすべて方法で、表示されました。


  • echo $MY_SECRET1`: 表示される


  • envコマンド: MY_SECRET1=This is secret message!が含まれている


  • node -e 'console.log(process.env)' : MY_SECRET1: 'This is secret message!'が含まれている。

一番簡単なecho $MY_SECRET1の結果です。値"This is secret message!"が表示されてます。


まとめ

「マージは慎重に!」と思いました。

マージしてauthorのCircleCIでビルドされれば環境変数は取得可能になってしまいます。

また、うっかりデバッグでauthorがenvを表示したりするのも危険ということが分かります。

たった3文字で大変なことが起こる可能性があります。

感想としては、

envをリモート端末に送信するような書かれてたりすれば、うっかり漏れたりする可能性がある気がしました。難読されたシェルとJSFuckとか色々読みにくくする方法はたくさんあると思います。

それら使ったりすればパッと見わからないように細工される可能性もあると思いました。

Travis CIだとコントリビューターがプルリクエストすると、authorのアカウントでCIでも動くので、Travis CIのときの環境変数の流出の可能性についてもちゃんと把握しておきたいです(ちょっと今Travis CI障害中なので先にCircle CI調べました)。

(追記:CircleCIでも、Build forked pull requestsオプションありましたね。Pass secrets to builds from forked pull requestsっていうオプションがあるくらいなのでこれがoffの限り、環境変数は渡されなさそうですね。)


蛇足

"This is secret message!"の"a"なかったです...