Techouse Developers Blog

テックハウス開発者ブログ|マルチプロダクト型スタートアップ|エンジニアによる技術情報を発信|SaaS、求人プラットフォーム、DX推進

GitHub Actionsのガードを高くする

ogp

この記事は、Techouse Advent Calendar 2024 15日目です。
昨日は 青木真一 さんによる Figmaプラグインを使って楽をしようとしたらCORSの壁に阻まれた でした。 15日目は keima が担当します。ちなみにTechouseではジョブハウス工場のモバイルアプリ開発をしています。

はじめに

Techouseに入社して純粋に思ったこととして、「セキュリティ意識が高いなぁ…」と思いました。 過去に勤務した経験のあるどの組織よりもセキュリティ意識がしっかりしていると感じました(もちろん近年はセキュリティ意識をより求められているというのもありますので、これまで勤めた組織もセキュリティ意識は向上していっているとは思います)。

お客様の情報をはじめとした情報資産の保護について、弊社の情報セキュリティ方針 を掲げるだけでなく、しっかり実行していくということに矜持を感じました。

そのような組織で働くと、自然と自分自身も同様の視点を持つようになります。そこで今回は、その視点を踏まえたうえでCI/CDに着目し、改善に取り組むことにしました。

TechouseではGitHub Actionsを用いてCI/CDを構築しています。 GitHub Actionsを用いるうえでは、その利便性と同時に、潜在的なセキュリティリスクを考慮する必要があります。ここからは、GitHub Actionsにおけるセキュリティリスクと、そのリスクを軽減できるツールについて取り上げていきます。

GitHub Actionsにおけるセキュリティリスク

GitHub Actionsにおけるセキュリティリスクは、条件によって色々と考えられるのですが、ひとまず業務でのリスクは以下があるということにします。

  1. 使用している action が汚染されないか
  2. GITHUB_TOKEN の権限が広く設定されていないか
  3. シェルスクリプトの実装ミスがないか

PRで変更が加えられたworkflowをPRのコンテキストのまま実行する設定をしない とかもあるような気はしますが今回は割愛)

それぞれ傾向と対策を考えます。

pinact: 使用している action が汚染されることを防ぐ

GitHub Actionsの特徴は、実行するイベントを全てシェルスクリプトで書かなくとも再利用できるようにパッケージ化されており、それが公開されており、公式だけでなく誰でも作成・利用できることにあります。

通常、私たちは uses: actions/checkout@v4 といった形でactionを指定します。これは、バージョン4の最新版を使うという指定です(厳密にはバージョン4の最新版であると配信者が指定したものを使う、詳しくは https://github.com/actions/toolkit/blob/main/docs/action-versioning.md )。

この仕組みは、常に不具合が修正された最新のバージョンを使い続けることが出来る半面、予期せず悪意のあるプログラムが自社のworkflowで実行されてしまう問題があります。また、事前にコードを読んで安全性を確認していたとしても、更新の際に汚染されたら意味がないわけです。

このような予期せぬ更新を防ぐために、タグではなくSHAコミットハッシュを指定することができます。 このような形で指定できます: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683

しかし、既存プロジェクトで置き換え作業をいちいち手作業でやっていくのは大変なので、ほぼ自動化できるツールが開発されています。ありがたい!

github.com

pinact作者による解説記事は、ここで私が説明したよりも詳細に解説されています。

zenn.dev

ghalint: GITHUB_TOKEN の権限が広く設定されていないか確認する

GitHub Actionsでは、 pushpull_request などで何らかのイベントを受けた結果として、その内容をコメントしたりステータスを変更するという操作をよく行います。 そういった操作は secrets.GITHUB_TOKEN をactionに提供するなどして実現すると思います。

docs.github.com

GITHUB_TOKEN によって許可される操作は、リポジトリやorgの設定によって変化します。詳しくは: https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#permissions-for-the-github_token

さて、上記リンクを確認して頂きたいのですが、permissiveな設定(リポジトリ設定の Actions > General > Workflow permissions の "Read and write permissions" 設定 )だとかなり広範囲にwrite権限が付与されています。おなじトークンで広範囲を読み書きできるのはややリスクがあります。

ということで、同じ設定の "Read repository contents and packages permissions" を設定すると、デフォルトでは書き込み権限を付与されなくなります。しかしそれでも広範囲のread権限は存在することになりますし、そもそも実運用としてwrite権限が完全にない状態は現実的ではないです。

GITHUB_TOKEN の推奨される設定方法として、workflow yamlで permissions 設定を行うことで、当該workflowにおいて指定したスコープに対して指定した権限のみが与えられた GITHUB_TOKEN が生成されるようになります。

例えば、 contentsread 権限のみ、 pull-requests は write権限を付与し、それ以外の権限付与はしないというような運用が可能になります。

それはそれとして、GitHub Actionsでは permissions の定義がされていないときは先ほどの Workflow permissions の設定を使うことになるので、そもそも permissions の定義をしていないことが問題になるというわけです。

以下のツールは、permissionが付与されていないworkflowを検知することが出来ます。残念ながら必要なpermissionを自動的に提案してくれたりはしませんので、そこは結構な手間がかかってしまいます。

他にも timeout-minutes の指定漏れなども指摘してくれます。モバイルアプリのビルドではデッドロックも稀に起こるので、タイムアウト設定は入れておいて損はないでしょう。

github.com

actionlint: シェルスクリプトの実装不備がないかチェックする

GitHub Actionsには様々なactionが提供されています。 しかし、これらでカバーできない処理もあるため、シェルスクリプトを動かせる run を使うこともよくあります1

ただし、雑にシェルスクリプトを実装するとスクリプトインジェクションの危険があります。特にコミットメッセージやPRタイトルなど自由入力値を取り得るものはインジェクションを引き起こしやすいです。

docs.github.com

これを防ぐためのツールがあります。shellcheckなどで静的解析を行ってくれたり色々チェックしてくれるのでなかなか高機能です。

github.com

どのようなことを見てくれるのかはこちらのドキュメントを確認して下さい。

github.com

workflowをチェックするworkflowをつくった

今回紹介したツールは、それぞれローカルで動かせるようになっていますが、CI環境で動作させてLintツールとして使用することも出来ます。

というわけで、私のチームではworkflowが変更されたときにチェックをかけるようなworkflowを実行させるようにして、常にガードを高くした状態を維持できるようにしています。

そして、ちょっと早いクリスマスプレゼントです!実際に作成したworkflowを公開します。

# Copyright (c) 2024 Techouse, Inc.
# Released under the MIT license
# https://opensource.org/licenses/mit-license.php

name: Lint GitHub Actions

on:
  pull_request:
    paths:
      - '.github/actions/**/*.yml'
      - '.github/workflows/**/*.yml'

jobs:
  lint:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    permissions:
      contents: read # actions/checkout
    steps:
      - name: Checkout
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          sparse-checkout: |
            .github

      - name: Install actionlint
        uses: jaxxstorm/action-install-gh-release@25d5e2dd555cd74f1fab9ac1e6ea117acde2c0c4 # v1.12.0
        with:
          repo: rhysd/actionlint
          cache: enable

      # pinact-action doesn't installs pinact itself
      - name: Install pinact
        uses: jaxxstorm/action-install-gh-release@25d5e2dd555cd74f1fab9ac1e6ea117acde2c0c4 # v1.12.0
        with:
          repo: suzuki-shunsuke/pinact
          cache: enable

      - name: Install ghalint
        id: install-ghalint
        uses: jaxxstorm/action-install-gh-release@25d5e2dd555cd74f1fab9ac1e6ea117acde2c0c4 # v1.12.0
        with:
          repo: suzuki-shunsuke/ghalint
          cache: enable

      - name: Run actionlint
        run: |
          # 以下URLのファイルを .github/ ディレクトリに配置することで、
          # actionlint の結果を GitHub のコード行にインラインで表示できるようになります
          # https://github.com/rhysd/actionlint/blob/main/.github/actionlint-matcher.json
          # echo "::add-matcher::.github/actionlint-matcher.json"
          actionlint -color

      - name: Run pinact
        uses: suzuki-shunsuke/pinact-action@a60b07ee63e41654915780a3297ff9f5f6b6db63 # v0.1.0
        with:
          skip_push: true

      - name: Run ghalint
        run: ghalint run
        env:
          GHALINT_LOG_COLOR: always

まとめ

明日のTechouse Advent Calendar 2024は harashunnn さんによる 「こんにちは。わたしはDocker build --secrets。あなたのクレデンシャルを守ります。」 です。


Techouseでは、社会課題の解決に一緒に取り組むエンジニアを募集しております。 ご応募お待ちしております。

jp.techouse.com


  1. 実は bash 以外も使える。pythonやpwsh(PowerShell Core)も使える。詳しくは https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell
  2. ちなみにこのことわざは、ChatGPTに「例えば、セキュリティを重視している会社に転職した結果、自分のコードなどもセキュリティを意識するようになった。こういうことを表すことわざや熟語はありますか」と聞いたら教えてくれました。勉強になるなぁ。