Skip to content

ci: 静的解析・CodeQL・定期実行・Dependabot を入れる - #17

Merged
ayutaz merged 4 commits into
mainfrom
ci/hardening
Aug 29, 2026
Merged

ayutaz merged 4 commits into
mainfrom
ci/hardening

Conversation

@ayutaz

@ayutaz ayutaz commented Aug 29, 2026 •

Copy link
Copy Markdown
Owner

監査した結果

CI/CD に実質的な穴があった。とくに、今回のマイルストーンで私が犯した誤りの大半は実行前に分かるものだった。

M2 の条件 7 を満たす作業で 7 回失敗した。うち 3 つは書き方の誤り:

  • 挿入位置を間違えて Windows の job に Linux 用の step を入れた
  • コンテナで走る job に sudo を残した(コンテナは root なので sudo が無い)
  • run: で呼ぶスクリプトの実行ビットを立てていなかった

どれも CI を 1 周(10〜20 分)回して初めて分かる形にしていた。静的に読めば分かるものを、実行して確かめていた。

足したもの

ci-lint.yml — 4 レーン、数分で終わる

レーン 何を捕まえるか
actionlint workflow の構文・式・run: の中の shell。上の 3 件はこれで実行前に出る
shellcheck hook(毎回のツール呼び出しで走る)と CI のセットアップ
PSScriptAnalyzer tools/ の大半は PowerShell なのに機械に読ませていなかった
リンク検査 文書の相互参照。CI が構造的に見逃す種類

PSScriptAnalyzer は Error だけを落とす。Warning まで落とすとこの repository の書き方(Write-Host を出力に使う等)と噛み合わず常時赤くなる。噛み合わない検査は無視されるようになるので、最初から通る幅にする。

codeql.yml — C++ と C#

public repository なので無料。sanitizer は「実際に踏んだ経路」を見るが、CodeQL は経路を実行せずに探す。重なっていないので、どちらかで他方を代替できない。

この層は M2 で整数の桁あふれ、M3 で handle table の use-after-free を踏んでいる。どちらも書いた本人には見えず、CI の緑を素通りした。

nightly.yml — 誰も push していない間に壊れることを見つける

今回の欠陥はまさにこの種類だった。 runner イメージが上がると、こちらが何も変えなくても成果物の要求が上がる。3 つ見る:

  • Linux 成果物の移植性 — コンテナの中身が変わって glibc が上がったら赤くなる
  • Windows / macOS の速いレーン — runner イメージの更新で壊れたら赤くなる
  • OpenCV artifact がまだ取得できるか — GitHub の artifact には保持期限があり、切れると restore が失敗して全レーンが止まる。「ある朝、誰も何も変えていないのに CI が全部赤い」を避ける

dependabot.yml

action は可変タグ(@v4)で固定しているので、上流が変わればこちらは何もしていないのに壊れる。逆に修正が出ても気づかない。PR にすれば差分として見え、CI が判定してから入る。NuGet(L3 の依存)も見る。

SECURITY.md / CONTRIBUTING.md

OSS として欠けていた。SECURITY にはこの境界で何が起きるかを具体的に書いた(buffer の長さ・handle の寿命・例外の脱出)。最も重い欠陥が「6 回に 1 回落ちるテスト」から見つかったことも書いてある —— 検査の網羅を誇らないため。

build-opencv.yml に permissions:

既定は広い。artifact の公開に要るのは書き込みだけである。これで全 workflow が最小権限になった。

検査そのものを検査した

  • 全 workflow が YAML として妥当(9 ファイル)
  • リンク検査を実際に走らせ、6 件の誤検出を見つけて直した —— 全部コードブロックの中で、実装計画が README を丸ごと引用している箇所だった。誤検出を出す検査は無視されるようになるので、fence を除外する形にした
  • 壊れたリンクを足すと落ち、戻すと通ることを確認(32 件を検査)

隠さず書いておくこと

  • この PR の workflow はどれも初回実行になる。 actionlint / shellcheck / PSScriptAnalyzer が既存のコードに何を言うかは、走らせるまで分からない。指摘が出たら直す
  • CodeQL の C++ 解析は OpenCV の取得とビルドを伴うので遅い(初回は 30 分程度を見込む)
  • まだ埋めていない穴: Windows の IL2CPP Player と macOS の Unity は CI に無い。game-ci が Windows ランナーで動かないため、これらは Unity Hub の CLI を使う別の作りが要る。別 PR で扱う

M2 の条件 7 を満たす作業で 7 回失敗した。**うち 3 つは実行する前に分かる
書き方の誤りだった**——挿入位置を間違えて Windows の job に Linux 用の step を
入れた、コンテナで走る job に sudo を残した、スクリプトの実行ビットを立てて
いなかった。CI を 1 周(10〜20 分)回して初めて分かる形にしていた。

静的に読めば分かるものを実行して確かめていた。そこを埋める。

## 足したもの

**ci-lint.yml** — 4 レーン。数分で終わるので重いレーンより先に落ちる。
- actionlint: workflow の構文・式・run: の中の shell まで読む。上の 3 件は
  これで実行前に出る
- shellcheck: hook(毎回のツール呼び出しで走る)と CI のセットアップ
- PSScriptAnalyzer: tools/ の大半は PowerShell なのに機械に読ませていなかった。
  **Error だけを落とす** — Warning まで落とすとこの repository の書き方と
  噛み合わず常時赤くなり、噛み合わない検査は無視されるようになるため
- リンク検査: 文書は相互参照が多く、リンク切れは CI が構造的に見逃す種類
  (CLAUDE.md が「CI が保証していないこと」の筆頭に挙げる文書の陳腐化の一形態)

**codeql.yml** — C++ と C#。public repository なので無料。sanitizer は
「実際に踏んだ経路」を見るが、CodeQL は経路を実行せずに探す。**重なって
いないので、どちらかで他方を代替できない。**

**nightly.yml** — 誰も push していない間に壊れることを見つける。
**今回の欠陥はまさにこの種類だった**——runner イメージが上がると、こちらが
何も変えなくても成果物の要求が上がる。3 つ見る:
- Linux 成果物の移植性(コンテナの中身が変わって glibc が上がったら赤くなる)
- Windows / macOS の速いレーン(runner イメージの更新で壊れたら赤くなる)
- **OpenCV artifact がまだ取得できるか**。GitHub の artifact には保持期限が
  あり、切れると restore が失敗して全レーンが止まる。「ある朝、誰も何も
  変えていないのに CI が全部赤い」を避ける

**dependabot.yml** — action は可変タグで固定しているので、上流が変われば
こちらは何もしていないのに壊れる。逆に修正が出ても気づかない。PR にすれば
差分として見え、CI が判定してから入る。

**SECURITY.md / CONTRIBUTING.md** — OSS として欠けていた。SECURITY には
**この境界で何が起きるか**を具体的に書いた(buffer の長さ・handle の寿命・
例外の脱出)。最も重い欠陥が「6 回に 1 回落ちるテスト」から見つかったことも
書いてある——検査の網羅を誇らないため。

**build-opencv.yml に permissions を足した。** 既定は広い。artifact の公開に
要るのは書き込みだけである。

## 確認したこと

- 全 workflow が YAML として妥当(9 ファイル)
- リンク検査を実際に走らせ、**6 件の誤検出を見つけて直した**——全部
  コードブロックの中で、実装計画が README を丸ごと引用している箇所だった。
  誤検出を出す検査は無視されるようになるので、fence を除外する形にした
- 壊れたリンクを足すと落ち、戻すと通ることを確認(32 件を検査)
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

ayutaz added 2 commits August 29, 2026 11:43
新しい 3 レーンは初回で全部落ちた。**指摘はどれも既存コードではなく、
私がこの PR で書いたものだった。** まさにこの検査が捕まえるべきものである。

**1. コメントが shellcheck の指示文になっていた**(actionlint が発見)

    # shellcheck 自身の重大度: error と warning は落とす。

`# shellcheck` で始まる行は**指示文として読まれる**ので、日本語が続くと
SC1072 / SC1073 の構文エラーになる。actionlint が workflow の `run:` の中身を
shellcheck に通して見つけた——「静的に読めば分かる」の実例が、足したその日に
出た形である。コメントを書き直し、意図した抑制(SC2086)は明示の
`# shellcheck disable=` で書いた。

**2. Invoke-ScriptAnalyzer に配列を渡していた**

    Cannot convert 'System.Object[]' to the type 'System.String'

`-Path` は 1 つずつしか取らない。まとめて渡せるつもりで書いていた。
foreach で回す形に直した。

**3. mkdir -p -m 755**(SC2174)

`-p` と併用すると権限が最深のディレクトリにしか効かない。作ってから
chmod する形に直した。

3 件とも、これらのレーンが無ければ気づかなかった。1 は「コメントのつもりが
指示文」という、目で読んでも気づきにくい種類である。
…r it

同じ誤りを 2 回踏んだ。**1 度目は説明そのもの、2 度目はその説明を説明する行**
である。どちらも行頭が「道具の名前 + 空白」のコメントで、指示文として
解釈され SC1072 / SC1073 の構文エラーになった。

目で読むと「コメントだから安全」に見える。2 回踏んだので機械に見させる。

tools/tests/OpenCvConfig.Tests.ps1 に検査を足した。**有効な指示文
(disable= / enable= / source= 等)は通し、指示文の形をした散文だけを
落とす。** 壊して確かめた:

- 散文を入れる → FAIL
- 有効な指示文を入れる → 通る(0 件)
- 戻す → all assertions passed

workflow と .sh の両方を見る。同じ罠は両方にある。
@ayutaz
ayutaz enabled auto-merge (squash) August 29, 2026 02:47
…wn script

残っていたのは 1 件で、しかも style レベル——`echo | sed` で字下げしている
箇所に「単純な置換なら変数展開を使え」(SC2001)。

sed に凝った書き方で応じようとして YAML を壊したので、素直な形にした:
表示したいだけなので `printf '  %s\n' $files` で足りる。パイプごと要らない。

語分割に頼る箇所(SC2086)は、下の実行と同じ理由なので同じ形で抑制を明示した。

**actionlint は workflow の `run:` の中身まで shellcheck に通す。** この
workflow 自身がその対象になっており、足した初日に自分の書き方を 3 回
指摘された(指示文になったコメント 2 回、これで 3 回目)。狙いどおりである。
@ayutaz
ayutaz merged commit 1b79be4 into main Aug 29, 2026
15 checks passed
@ayutaz
ayutaz deleted the ci/hardening branch August 29, 2026 02:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants