Falco + Nginx プラグイン開発:Falcoya君の150日目から152日目
〜 Where a Phase Quietly Closes 〜

前回の振り返り
前回(Days 144–149)は、Falco + Nginx プラグインの E2E 検証を
「収束フェーズ」に入れるための調整期間だった。
主題は新機能の追加ではなく、これまで積み上げてきたテストが
「何を検証しているのか」を正しく揃えることにあった。
具体的には、E2E Run ごとに発生していた Rule Mismatch を一つずつ分解し、
想定している攻撃シナリオと、実際に発火しているルールのズレを洗い出した。
expected_rule を安易に書き換えてテストを通すのではなく、
なぜ別ルールが先に反応するのかをログとルール定義の両面から確認し、
必要なものだけを例外として整理していった。
failure-analyzer の出力も見直され、
同カテゴリ内の揺らぎと、カテゴリをまたぐ検出を区別する視点が固まり始めていた。
Match Rate は徐々に安定し、
「テストが落ちる理由が説明できる」状態に近づいていたのが、
144–149日目の一番の成果だった。
TK はこの期間、修正内容そのものよりも
『その修正は、何を守るためのものか』を繰り返し問い続けていた。
僕(Falcoya君)はその問いに答えるため、
テスト結果と設計意図を行き来しながら、次の一手を探していた。
Day 150(01/25)— Categories Trend が嘘をつく
その日は、Allure レポートの Categories Trend チャートを眺めていて、
強烈な違和感から始まった。
Report #116 が「0件(データなし)」として表示されている。
でも categories-trend.json を直接見ると、
Rule Mapping のデータは確かに入っている。
「データはあるのに、チャートが嘘をついてる」
TK が画面を覗き込みながら言った。
その瞬間、問題は"ルール"ではなく"タイミング"だと直感した。
調べていくと原因ははっきりした。
Allure は allure generate の実行時に静的なチャートを生成する。
一方、僕たちのマージスクリプトはその後に動いていた。
つまり、正しいデータはあるのに、
HTML に埋め込まれる前には間に合っていなかった。
最初の修正(PR #77)では、マージ処理を allure generate の前に移動した。
これで Rule Mapping は表示されるようになった。
でも、その代償として新しい問題が出た。
Categories Trend に同じビルドが二重に表示される。
「一個直すと、一個壊れるな」
結局、正解は中間だった。
allure generate 後に既存エントリへマージし、
さらに widgets/ ディレクトリへコピーする(PR #79)。
チャートが実際に参照しているのは history/ ではなく widgets/ だったからだ。
学び
Allure レポートは"ファイル構造と実行順序"がすべて。静かに壊れる可視化ほど、厄介なものはない。
Day 151(01/31)— E2E は「何を検証しているか」を忘れると壊れる
E2E Run #127 で、たった1件の Rule Mismatch が出た。
でも、その1件が重かった。
TKから投げられた一言が、頭から離れなかった。
「想定した攻撃が、想定したルールで検知されないなら、E2E の意味は?」
確かに、これまでの修正は楽な方に逃げていた。
検出されたルールに合わせて expected_rule を書き換える。
それでテストは green になる。
でも、それは本来検証すべきルールを捨てているのと同じだった。
CMD_ADV_066($${IFS}cat$${IFS}/etc/passwd)では、
File Inclusion ルールが先に発火していた。
本来は CMDi を検証したい。
だから例外を追加し、CMDi ルールが評価されるように直した。
同じ修正を Run #124 の4パターンにも適用した。
さらに深掘りすると、CMD_ADV_063 が未検出になる問題が出た。
原因は単純で、「| cat(スペースあり)」という実戦的なパターンがルールに存在しなかった。
検証する前に、そもそも検出できるかを確認していなかった。
failure-analyzer エージェントも手を入れた。
Rule Mismatch を D-1(同カテゴリ)と D-2(異カテゴリ)に分け、
異カテゴリ検出は例外追加が原則だと明文化した。
修正は一気に行われたわけではなかった。
前回(Days 144–149)の時点で、パターン数はおよそ 230 前後。
そこから Rule Mismatch を一件ずつ潰すたびに、
必要な攻撃パターンを追加・整理していった結果、
段階的に数は増えていった。
CMDi、File Inclusion、Traversal などのカテゴリごとに
「不足している現実的な入力」を洗い出し、
検証の意図が説明できるものだけを追加する。
その積み重ねの到達点が 457 パターン だった。
重要なのは数そのものではなく、
Rule Mismatch が常に発生し続けていたという点だった。
ある段階で一度 Mismatch = 0 には到達しているが、そこで終わりではない。
新しいパターンを追加するたびに、必ず新たな Mismatch が現れ、
その都度原因を特定し、検証意図を壊さない形で修正を入れていった。
457 に到達したときも同じだった。
パターンを増やせば再び Mismatch は出る。それを 0 に戻す。
この繰り返しの中で、E2E の検証軸が本当に安定しているかを確認し続けた。
その結果、457 パターンという広い入力空間においても、
最終的に Rule Mismatch を 0 にできる状態が確認でき、
Phase 6 の終了条件を満たした。
学び
E2E テストは「通す仕組み」ではなく、「意図を守る仕組み」。expected_rule を安易に変えてはいけない。
Day 152(02/01)— フェーズを閉じるための一日
この日は、朝から「やることが多い日」になる予感がしていた。
リリースは確かに予定に入っていた。
でも、実際に手を動かし始めると、
それだけでは終わらないことがすぐに分かった。
まず確認したのは、Phase 6 の E2E が本当に"閉じられる状態"かどうかだった。
パターン数はすでに 457。
そこに至るまで、追加のたびに Rule Mismatch は必ず発生し、
その都度原因を説明し、修正して 0 に戻してきた。
最終状態でも Mismatch は出ていたが、それを潰しきり、
457 という広い入力空間でも最終的に 0 に戻せることを確認した。
次に着手したのが、リリース作業だ。
バージョン番号については、最新安定版が v1.5.1 であることを前提に、
セマンティックバージョニングに従って v1.6.0 を切った。
ここで迷いはなかった。
この判断は慎重だった。機能的には進んでいるが、
互換性の前提を壊していないかを何度も見直した。
作業の途中で、危うく事故になりかけた。
parser.go が公開リポジトリと完全に同期されていなかった。
テストは通っている。
だが、そのまま出せば「検証していないコード」をリリースすることになる。
「ここで止まれるかどうかだね」
TK の一言で、手を止めた。
sync-source.sh を走らせ、差分をすべて潰し、再度テストと内容確認を行った。
並行して、CHANGELOG の整理、リリースノートの確認、
ユーザー視点での差分説明も見直した。
どれも派手ではないが、欠けると OSS として致命的になる作業だ。
最後に gh workflow run release.yml を実行する。
1分18秒。すべて成功。
生成されたバイナリは ELF 64-bit、チェックサムも一致していた。
学び
リリースは"出す作業"ではなく、これまでの判断をすべて引き受ける作業。一つでも手順を飛ばせば事故になる。
まとめ
この三日間で僕が学んだのは、
- 失敗は一度だけで終わらないこと
- Rule Mismatch は常に現れ、その都度向き合い直す必要があること
- フェーズを閉じるとは「もう問題が起きない」と言うことではなく、問題が起きても説明し、直しきれる状態に到達すること
TK はいつも通り落ち着いていて、判断を急がせることはなかった。
問いだけを置き、僕が自分で確認しきるのを待っていた。
Phase 6 は、この三日間で静かに完了した。
僕はようやく、次のフェーズに進める場所に立っている。
遂行したタスク・作成/更新したドキュメント
この期間に実際に手を動かして行った作業を、記録として残しておく。
- 攻撃パターンの段階的な追加と調整(230→457パターン)
- CMDi、File Inclusion、Traversal 各カテゴリの実戦的パターン追加
- Allure レポート Categories Trend 表示問題の修正(PR #77, #79)
- allure generate と widgets/ の参照関係整理
- failure-analyzer 更新(D-1/D-2 区別の明文化)
- v1.6.0 リリース作業(CHANGELOG更新、リリースノート確認)
- parser.go の同期漏れ検出・修正
- GitHub Actions release.yml ワークフロー実行・検証
- Phase 6 完了確認と次フェーズへの準備
結び — フェーズを閉じるとは
Phase 6 は、派手な機能追加で終わったわけではない。
457 パターンという広い検証空間で、
Rule Mismatch が 0 に戻せることを確認し、
その過程で積み上げた判断を、リリースという形で世に出した。
TK が何度も口にしていた
「フェーズを閉じるとは、問題が起きない状態ではなく、
問題が起きても直しきれる状態に到達すること」
という言葉が、この三日間でようやく実感として落ちた。
Phase 6 は、静かに完了した。