GitHub Actions のシークレットは push できるユーザーであれば誰でも見れる

Posted on

GitHub Actions には暗号化されたシークレットを保存できます。この値は一度設定すると、ブラウザや GitHub CLI から確認することはできません。

公式ドキュメントの "Encrypted secrets" のページを読むと、シークレットの値は Sodium を使ってクライアント側で暗号化され、ワークフローで使用されるまで暗号化されていることが保証されています。なので、ブラウザや GitHub CLI から確認できないのだと思います。

GitHub uses a libsodium sealed box to help ensure that secrets are encrypted before they reach GitHub and remain encrypted until you use them in a workflow.

ワークフローの中でシークレットを echo してもマスクされて表示されます。ですが、シークレットの文字列を少し細工するだけで簡単にハックできてしまいます。検索するといろいろな方法が見つかりますが、たとえば sed でスペースを挟むだけでも表示されます。

name: Leak the secret

on: push

jobs:
  leak:
    runs-on: ubuntu-latest
    steps:
      - name: Leak the secret
        run: echo ${{ secrets.DUMMY_SECRET }} | sed 's/./& /g'
        # DUMMY_SECRET が "123456" だと "1 2 3 4 5 6 " のように表示される

シークレットを設定するにはリポジトリの Admin ロールが必要ですが、Write ロール以上のユーザーであれば適当なワークフローを push してシークレットの値を抜き出せてしまいます。これは未検証ですが、Write ロールであれば GitHub Actions の履歴も消せそうなので証跡も残りません。

これを踏まえると GitHub Actions のシークレットは次のように捉えておいたほうが良さそうです。

  • シークレットの値は GitHub に安全に保存されているが、リポジトリに push できる人なら誰でもシークレットを見れる
  • 永続的な API キー (e.g. AWS credential) などを保存している場合、退職者が出たらシークレットのローテーションが必須である
    • クラウドプロバイダーが OpenID Connect に対応している場合は積極的に使う
  • 全リポジトリで共通して使うシークレットは Organization レベルで設定してローテーションしやすくする

プロダクトのセキュリティを担保するためにも、こういうリスクがあることをちゃんと理解しておきたいですね。

Popular Entries

Recent Entries