Dependabot
のPull Request(以下PR)が作られた際に開始したGithub Actionsワークフローが Secrets
を参照できずに失敗していたので原因を調べてみました。
2021/3/1から適用になった以下のUpdateが影響していて、 Dependabot
から実行される Github Actionsワークフローは読み取りだけが可能な GITHUB_TOKEN
のみ使うことができ、いかなる Secrets
も使えなくなるという変更が原因でした。
なので、例えばpushイベントトリガーで実行されるワークフローの中で Secrets
として追加しておいたPersonal access tokensを使って、取得したカバレッジのサマリをコメントで追加したり、自動でラベルを追加するといった書き込み(write)権限が必要な場合は、ワークフローが落ちる状況になっていました。
結論
以下のように
dependabot
から実行されされた場合はpull_request_target
トリガーの時のみ実行dependabot
以外から実行された場合はpull_request_target
トリガー以外の時に実行
するようにしました。
on: push: pull_request_target: workflow_dispatch: name: Test jobs: test: runs-on: ubuntu-latest if: (github.event_name == 'pull_request_target' && github.actor == 'dependabot[bot]') || (github.event_name != 'pull_request_target' && github.actor != 'dependabot[bot]') steps: - uses: actions/checkout@v2 if: (github.event_name == 'pull_request_target' && github.actor == 'dependabot[bot]') with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 - uses: actions/checkout@v2 if: (github.event_name != 'pull_request_target' && github.actor != 'dependabot[bot]') with: fetch-depth: 0 - name: SonarCloud Scan uses: SonarSource/sonarcloud-github-action@master env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
actions/checkout
のオプションに ref: ${{ github.event.pull_request.head.sha }}
がないと、 main
ブランチをチェックアウトしてしまうようなので pull_request_target
の場合は同時にこのオプションを付けるようにすると良いようです。(参照)
このように対応することに至った具体的な経緯を共有していきます。
失敗していた原因
実行結果の詳細を見るとSet the SONAR_TOKEN env variable.
というエラーが発生しており、 Secrets
に設定していた値が取れていないことが確認できました。
以下のリポジトリで、同様の状況を再現してみましたので、よろしければ参考にしてみてください。
対応方針の検討
主に以下の3つのドキュメント・Github issueを参照しました。
- 2021/2/19に公開されたGithubブログの記事 (GitHub Actions: Workflows triggered by Dependabot PRs will run with read-only permissions)
- 2020/12/15に公開されたGithubブログの記事 (Keeping your GitHub Actions and workflows secure: Preventing pwn requests)
- dependabot-coreの該当issue
これらの情報から大きく分けて3通りの対応方法があることが分かりました。
- ①pull_request_targetトリガーを使う
- ②workflow_runトリガーを使う
- ③Dependabotを諦めてRenovateに乗り換える
また、①と②のどちらを適用するかは場合によって異なります。いずれの場合もwrite権限が付与され Secrets
にアクセスできるようになる、という点は変わりません。
- PR自体を更新する必要がある場合
- => ②workflow_run
- コメントやラベル等を追加しPRを構成するだけで更新しない場合
- => ①pull_request_target
①pull_request_target
トリガーを使う
2021/2/19に公開されたGithubブログの記事
によると、write(書き込み)権限があるトークンが必要な場合、以下の2020/12/15に公開されたGithubブログの記事に書いているリスクを把握したうえで pull_request_target
を使ってください、という記述があったのでリスクに関する記述を読んでみました。
リスクに関する記述1: 適用用途
pull_request_target
トリガーに関して以下の記述がありました。
The reason to introduce the pull_request_target trigger was to enable workflows to label PRs (e.g. needs review) or to comment on the PR. The intent is to use the trigger for PRs that do not require dangerous processing, say building or running the content of the PR.
pull_request_targetトリガを導入した理由は、ワークフローでPRにラベルを付けたり(例:needs review)、PRにコメントを付けたりできるようにするためでした。このトリガーは、PRの内容を構築したり実行したりするような危険な処理を必要としないPRに使用することを意図しています。
今回遭遇したエラーは、この用途に該当するGithubワークフローで発生したものでした。
リスクに関する記述2: 注意点
pull_request_target
トリガーの中でどのような処理を実行しても良いかを考えるうえで、以下の記述が参考になりました。
a workflow triggered on pull_request_target still has the read/write repository token in memory that is potentially available to any running program.
If the workflow uses actions/checkout and does not pass the optional parameter persist-credentials as false, it makes it even worse.
The default for the parameter is true. It means that in any subsequent steps any running code can simply read the stored repository token from the disk.
日本語にすると
pull_request_target でトリガーされたワークフローでは、メモリ内に読み取り/書き込み可能なリポジトリトークンが残っており、実行中のプログラムから利用できる可能性があります。
ワークフローが actions/checkout を使用していて、オプションのパラメータ persist-credentials を false にしていない場合は、さらに悪い状況になります。このパラメータのデフォルトはtrueです。
これは、後続のステップで、実行中のコードがディスクから保存されたリポジトリトークンを単純に読み取れることを意味します。リポジトリへの書き込みアクセスやシークレットが必要ない場合は、pull_request トリガーを使用してください。
という感じかと思います。
②workflow_run
を使う
リスクに関する記述1: 適用用途
workflow_run
トリガーに関して以下の記述がありました。
Together with the pull_request_target, a new trigger workflow_run was introduced to enable scenarios that require building the untrusted code and also need write permissions to update the PR with e.g. code coverage results or other test results.
pull_request_target と共に、新しいトリガ workflow_run が導入され、信頼できないコードの構築を必要とするシナリオや、コードカバレッジの結果やその他のテスト結果などで PR を更新するための書き込み権限を必要とするシナリオを可能にしました。
Dependabot
によって実行される Github actions
ワークフローの中でPRを更新するようなケースでは workflow_run
を使うと良さそうです。
リスクに関する記述2: 注意点
workflow_run
トリガーの中でどのような処理を実行しても良いかを考えるうえで、以下の記述が参考になりました。
To do this in a secure manner, the untrusted code must be handled via the pull_request trigger so that it is isolated in an unprivileged environment.
これを安全に行うためには、信頼できないコードは、権限のない環境で隔離されるように、pull_requestトリガを介して処理されなければなりません。
③Dependabotを諦めてRenovateに乗り換える
対応が煩雑なので Renovate
への置き換える方もでてきているようです、合わせて検討すると良いかもしれません。
対応したコード
用途に適した対応が①pull_request_target
トリガーを使うだったので、Github issueコメント記載されていた対応コードのサンプルを参考に対応してみました。
ワークフローが正常に動くようになることを確認した検証用リポジトリも共有しておきます。 github.com
private registriesを使う場合
2021/3/15に以下のリリースがあり、GitHub Packagesやnpm等のプライベートレジストリを使ってパッケージの更新を行っている場合はよりセキュアに Secrets
を使うことができるようになったので、こちらの方法と併せて対応すると良さそうです。
Dependabot secretsの検証
もしかすると、 private registriesで使用可能な以下の Dependabot
の Secrets
を設定することで、Github actions
ワークフローから参照できるようにならないかな、と思って試してみたのですがうまくいきませんでした。dependabot.ymlの中からしか参照できないようです。
Github actions
ワークフローで行っている Secrets
を使った処理を Dependabot
の機能に移せる場合に、 Dependabot
のprivate registriesの使用を検討すると良さそうです。
検証した際のGithubリポジトリを以下に記載しておきます。