0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SAST(Semgrep)をCIに組み込んだ話

0
Posted at

個人でWebアプリを開発してて、「そろそろセキュリティ周りもちゃんとしたいな〜」と思い、GitHub ActionsにSAST(静的解析でコードの脆弱性を検出するやつ)を組み込んでみました。

ただしprivateリポジトリ + 個人開発なので、お金は一切かけたくないという制約付き。この記事はその技術選定〜導入〜つまずいたところまでのメモです。

どんなシステムに入れたか

  • Next.js(App Router) + TypeScript のWebアプリ(タスク管理系のSaaS)
  • API部分はAWS Lambda、DBはAurora Serverless v2(PostgreSQL)
  • フロントは S3 + CloudFront で配信するサーバーレス構成
  • CI/CDはGitHub Actions。PRごとにlint/型チェック/テスト/ビルドを回すci.ymlと、PRごとに検証環境を自動で立ち上げるpr-preview.ymlが既にある状態

要は「よくあるサーバーレスWebアプリ + GitHub Actions」くらいの構成だと思ってもらえればOKです。

要件

  • GitHub ActionsのCIに組み込む
  • コストは今まで通り最小限(≒ 無料)
  • 最低限Web/APIのOWASP Top10はチェックしたい

技術選定

まず思いつくのはGitHub CodeQL(GitHub純正のコードスキャン)ですが、ここで詰みポイントが一つ。

CodeQLの解析自体はタダでも、結果を「Security」タブに出す「コードスキャン」機能は、privateリポジトリだとGitHub Advanced Security(有料・コミッター課金)が必須

個人開発のprivateリポジトリだとこれが結構痛い出費になるので却下。publicリポジトリなら無料なんですが、今回はprivate運用なので使えませんでした。

というわけで選んだのが Semgrep(OSS版のCLI) です。

選択肢 ジャッジ 理由
Semgrep OSS CLI ◎ OWASP Top10特化ルールセットが無料で使える。ログイン・トークンも不要
GitHub CodeQL ✕ privateだとGHAS(有料)必須
Snyk/Bearer等 △ 無料枠はあるけどアカウント管理・回数制限が発生する

Semgrepは公式のOSSルールレジストリにp/owasp-top-tenというOWASP Top10特化ルールセットがあって、これを使えば要件をドンピシャで満たせます。CLI自体もOSSで、semgrep.dev(有料のAppSec Platform)にログインしなくても普通に動きます。GitHub Actionsの実行時間(無料枠内)しかコストがかからないのが決め手でした。

実装

ワークフローはこんな感じ。公式のDockerイメージにsemgrepが入ってるので、それを使うだけです。

name: SAST

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

jobs:
  semgrep:
    runs-on: ubuntu-latest
    container:
      image: semgrep/semgrep
    steps:
      - uses: actions/checkout@<コミットSHA> # v4.4.0

      - name: Semgrep scan (OWASP Top 10 + secrets)
        run: semgrep scan --config p/owasp-top-ten --config p/secrets --error

ポイントはこのくらい:

  • --config p/owasp-top-ten: OWASP Top10特化ルール(必須要件)
  • --config p/secrets: ハードコードされた認証情報の検出。誤検知が少なくて軽量なので追加
  • --error: 指摘があったらジョブを失敗させる(ブロッキング)
  • GitHubの「コードスキャン」機能(SARIFアップロード)は使わない。これもprivateだとGHAS要求されるので、結果はジョブのログにそのまま出すだけにしてる

初回スキャンでいきなり詰んだ話

意気揚々とPRを出したら、初回スキャンでいきなり12件のブロッキング指摘。「うわ、既存コードやばいのか…?」と身構えましたが、中身を見たら全部同じルールでした。

github-actions-mutable-action-tag
GitHub Actions step uses a mutable tag or branch reference...
Pin the reference to a full 40-character commit SHA instead

要するに「uses: actions/checkout@v4みたいなタグ参照は書き換え可能だから危ないよ、コミットSHAに固定してね」という指摘でした。サプライチェーン内の脆弱性にかかわる指摘ですね。Log4jで嫌な思いをした身としては、真っ当な指摘ではあります。

ただこれ、OWASP Top10(Web/APIの脆弱性)とは毛色が違う「CI/CDのサプライチェーン対策」の話。しかも自分のワークフローファイル全部(4ファイル・12箇所)に影響する変更だったので、いったん--exclude-ruleでこのルールだけ除外してPRをマージ可能な状態にしました。

その後、GitHub APIで各アクションのv4タグが指す最新コミットSHAを調べて、

# before
- uses: actions/checkout@v4

# after
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

という感じで全部SHA固定に変更。AWS認証まわりのアクションも含めて直したので、ちゃんとデプロイが壊れないかも実際にCIを走らせて確認してから--exclude-ruleを外しました。

まとめ

  • privateリポジトリ + 個人開発でコストゼロのSASTを入れるなら、Semgrep OSS CLIがおすすめ(CodeQLはprivateだと有料機能が絡んでくる)
  • p/owasp-top-tenを使えばOWASP Top10特化のチェックがそのまま無料で手に入る
  • 初めて導入するときは、既存コードに対して思わぬジャンルの指摘(今回はCI/CDのタグ固定)が出ることがあるので、「今回の要件に関係ある指摘か」を切り分けてから対応するとスムーズです
  • ついでにGitHub Actionsのコミットハッシュ固定もできて、セキュリティ的に一石二鳥でした

以上、個人開発のセキュリティ強化メモでした。同じ悩みの人の参考になれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?