🐙

GitHub Actionsで "このアウトプットはシークレット含んでそうだから出力をスキップするよ"と言われてしまった時の対処法

2023/12/09に公開

はじめに

最近触っているGitHub Actionsで、"Warning: Skip output 'hogehoge' since it may contain secret"がでて困ったので、その回避方法について記載する。

経緯

以下の様なイメージのworkflowを作った。

(略)

jobs:
  job1(あるサービスにファイルをアップロード & 一時的に使えるダウンロード用のURLを発行する)
    runs-on: ubuntu-latest
    outputs:
      {生成したダウンロード用のURL}
  steps:
    step1(サービスにアクセス、ファイルをアップロードする)
    step2(一時的に使用できるダウンロード用のURLを発行する)
		
  job2(上記のjobで生成されたURLを受け取り、そのURLを使ってSelf-hosted runnerとして使用しているローカルマシンでダウンロード)
    runs-on: ローカルマシン
    needs: job1
    steps:
      step1(job1のoutputsから受け取ったダウンロード用URLを叩く)

...しかしworkflowを実行してみると、ダウンロードが実行されていない。job2のログを見ると、URLが受け取れていない(空文字列になっている)事が分かり、更にjob1のログを見ると、以下の様な警告メッセージが出力されていた。

こちらにある様に、GitHub ActionsではリポジトリやOrganizationごとにシークレットと呼ばれる機密情報を設定し(名称そのまま)、workflow内で使用する事ができる。一般的には、外部サービスへアクセスする際のID/PWなど、「workflowの処理で必要だが、他の人に見られるとマズい情報」のために使用するイメージ。
また、これらの値をGitHub Actionsのログで出力しようとすると、自動的にマスキングが行われ、元の文字列が何かは分からない様になっている。

自分は今まで、シークレットに対して行われる特別な処理はこのログ出力時のマスキングぐらいしかないと思っていたが、どうやらjobを跨いで、このシークレットを含む様な情報を渡そうとすると、GitHub Action側がそれを防ぐ仕組みがあるらしい[1]。workflowにおいて、ログの文字列がマスキングされる事が、workflowの動作そのものを妨げるケースは少ないと思うが、今回の現象は動作そのものに影響してくるのが厄介。

対処方法

自分が調べた限りだと、上記のGitHub Actionsの心遣いをOFFにする様な設定は用意されていない様だった。
なので、以下の様な方法で対処した。

  1. job1のoutputsに生のURLを格納するのではなく、何らかの方法でエンコードした文字列を格納する
  2. job2はエンコードされた文字列を受け取り、それをデコードしてURLを復元する

要はjobからjobにoutputを渡す際に、GitHub Actionsの検閲に引っからない様に一時的に別の文字列に置き換えてしまおう、というアイデア。
世の中に文字列をエンコード/デコードする方法は色々あるが、今回自分が試したのは以下である。

  • base64
  • GPG

前者はバイナリを文字列に変換する仕組み、後者は暗号化するための仕組みであるという認識(間違っていたらすみません)。
ネット上では、「base64だけでいけた!」という書き込みもあったのだが、自分の場合は何故かbase64でエンコードした文字列も、シークレットを含んでいると判定されて送れなかったので[2]、別途シークレットに登録したパスフレーズを用いてGPGで暗号化した文字列を更にbase64でエンコード/デコードする様にした所、上手く行った。

参考

https://medium.com/@adel.muhandes/securely-passing-secrets-between-github-action-jobs-a-simple-guide-76ec9d838d0f
https://nitratine.net/blog/post/how-to-pass-secrets-between-runners-in-github-actions/

脚注
  1. 具体的にどの様なロジックで、シークレットが含まれている可能性があると判定しているのかは気になる所。完全にシークレット文字列を含んでいる場合はNGなのは分かるが、例えばその部分文字列を含んでいる場合もNGなのかとか。 ↩︎

  2. この辺りは詳しくないので分からないのだが、base64エンコードした文字列に、元の文字列の部分文字列が含まれることもあり得るのだろうか?ひょっとしたら他に登録しているシークレットが引っかかっているのかもしれないが、GitHub Actionsは具体的にどのシークレットが含まれていると判定したかは教えてくれないので謎である。 ↩︎

Discussion