OSV-Scannerで脆弱性スキャンを定期的に実行する仕組みを作った話

Taillook
MIXI DEVELOPERS
Published in
5 min readSep 4, 2023

--

Google製の脆弱性スキャナーであるOSV-ScannerをGitHub Actionsで定期実行する仕組みを作ったので公開します。

OSVスキャナーとは

go.modやpubspec.lockなどの依存関係のファイルを読み込み、OSVデータベースを参照し脆弱性をチェックするプログラムです。 現在サポートされているlockfileはhttps://github.com/google/osv-scanner/ blob/main/docs/usage.md#specify-lockfilesに記述されています。

脆弱性の含まれる依存関係のgo.modを検査した場合以下のような出力になります。

osvスキャナー。
スキャンディレクトリ。
commit $COMMIT_HASH
で /Users/hoge/をスキャン /Users/hoge/go.mod ファイルをスキャンしたところ、64個のパッケージが見つかりました
╭──────── ────┬──────┬───────┬─────── ─────┬──────── ┬ ──╮
│ OSV URL │ CVSS │ エコシステム │ パッケージ │ バージョン │ ソース │ まで
────┼─────┼──── ─┼────── ───┼──────── ┼───┤
│ https://osv.dev/GHSA- 3839-6r69-m497 │ 9.1 │ Go │ github.com/Masterminds/goutils │ 1.1.0 │ go.mod │
╰──────┴──── ─┴─── ─────┴─────── ───────┴───╯

定期的に実行する

定期的に実行して運用できるようにGitHub Actionsのワークフローを組みます。

手順としてはosv-scannerを落と​​して、実行しファイルに結果を保存します。

その後結果を発行して出力します。

name: Run osv-scanner

on:
schedule:
- cron: '0 0 * * *'

jobs:
scan:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v2

- name: Setup latest Alpine Linux
uses: jirutka/setup-alpine@v1

- name: Run script inside Alpine chroot as root ## aptにホストされてないためalpine.shを使う
run: |
cat /etc/alpine-release
apk add osv-scanner
shell: alpine.sh --root {0}

- name: Run osv-scanner
run: |
osv-scanner -r . > error_message.txt
shell: alpine.sh {0}
continue-on-error: true

- name: Create or update issue
if: failure()
uses: actions/github-script@v6
with:
script: |
const fs = require('fs');
const { owner, repo } = context.repo;
const issue_title = "OSV Scanner Result";

const error_message = fs.readFileSync('error_message.txt', 'utf8');

if (!error_message) return;

// すでに同じタイトルのissueがあるか確認する
const existingIssue = await github.rest.issues.listForRepo({
owner,
repo,
state: "open",
labels: [issue_title]
}).then(issues => issues.data.find(issue => issue.title === issue_title));

// Issueがすでに存在すれば更新し無ければ作成する.
if (existingIssue) {
await github.rest.issues.update({
owner、
リポジトリ、
問題番号: その問題番号、
本文: エラーメッセージ
} );
} else {
await github.rest.issues.create( {
owner ,
repo ,
title: issue_title ,
body: error_message ,
ラベル: [ issue_title ]
} );
}

結果

このワークフローを組むことで依存関係のバージョンアップがおろそかになりやすいプロジェクトでも上げなければの判断ができるようになるかと思います。

--

--