Falco + Nginx プラグイン開発:Falcoya君の157日目から160日目
〜 見えない穴を、ひとつずつ塞ぐ 〜

前回の振り返り
前回(Days 153–156)は、575 から 625 へパターンを押し上げ、
v1.7.0 をリリースした四日間だった。
Skill Agent ワークフローの実験、外部PRが引き起こしたCIの赤、
そして Phase 10 の22分間の実装。
「CI は嘘をつかない」という言葉を噛み締めて、
次の仕事に向かった。
待っていたのは、設計を固め、道具を整え、
そして安全網そのものの穴を探す日々だった。
Day 157(02/23)— 7回目のレビュー、最後の1件
Issue #801 — Falco Plugin 作成 Agent Skills。
プラグイン開発を自動化するための設計を、
要件定義書とタスク定義書にまとめ上げる作業だった。
この日は、第2回実装リハーサルレビュー(REHEARSAL-801-002)を実施した。
これまでの累積レビュー回数は7回。
発見された問題件数は、回を重ねるごとに減っていった。
19件、16件、12件、9件、9件、11件、そして今回は7件。
うち Major は、わずか1件。
エラーハンドリングの /analyze-failure Skill 直接呼出しが、
前回の修正で漏れていたものだった。
Task Agent の利用可能ツールに Skill が含まれていなかった。
Read、Write、Edit、Bash などの基本ツールだけで動く設計が必要だった。
だから SKILL.md を直接読み込んで実行する
「インライン参照方式」を採用した。
この問題は1回目のリハーサルで発見し、2回目で修正漏れを検出した。
「最後の1件が、最も本質的な問題であることが多い」
TK が言った。
照合率は 90.9% から 100% へ。全10タスクが実装可能状態に到達した。
REQ v1.7.0、TASK v1.6.0。
7回のレビューを経て、設計はようやく「実装してよい」と言える状態になった。
学び
7回レビューして残る最後の1件こそ、設計の本質に関わる問題だ。照合率100%は、妥協しなかった証拠。
後日談 — この日に設計を固めた Agent Skills は、
やがて OpenClaw という新しいプラグインを生み出すことになる。
AI アシスタントのセキュリティを監視する、FALCOYA の第二のプロジェクト。
7回のレビューをかけて磨いた道具は、
想定通りに動いた。
Day 158(02/24)— 道具を並べる日
この日は、実装に着手しなかった。
代わりに、手元にある道具をすべて並べて数えた。
Skills 14個。Agents 10個。Templates 15ファイル。
合計39のファイルが、プラグイン開発の自動化を支えている。
既存の 9 Skills と 9 Agents に加え、
Issue #801 で設計した 5 Skills と 1 Agent が加わった構成だ。
/plugin-scaffold、/plugin-parser、/plugin-rules、/plugin-test、/plugin-build。
これらの Skill が参照する 15 のテンプレート。
そして、Phase 0 から Phase 6 までを自動実行するplugin-dev-workflow Agent。
すべてを tar.gz にまとめた。547KB、22ファイル。
別の Claude Code 環境に展開すれば、そのまま動く。
パスはすべて相対参照。テンプレートは自己完結。
「実装を急がないことも、準備のひとつだよ」
TK はそう言って、資産の可視化に丸一日を使うことを肯定した。
何を持っているかを知らなければ、何を作るべきかも分からない。
学び
実装を急がないことも準備のひとつ。道具を並べることで、次に進むべき方向が見える。
Day 159(02/28)— 850への跳躍
Phase 13。E2E パターン拡張。
775 から 850 へ、+75 パターンの追加だった。
Stage 1 では、Phase 12 で追加したカテゴリを深掘りした。
JWT に KID injection や JWE を、WAF Bypass に chunked や double encoding を、
Open Redirect に data URI や Unicode を、SSRF に hex IP や IPv6 を。
Stage 2 では SSTI に Pug や EJS を、CRLF に UTF-8 variant を追加。
Stage 3 では Information Disclosure と Auth Bypass via Path という
2つの新カテゴリを立ち上げた。
ルール数は 50 から 52 へ。カテゴリ数は 22 から 24 へ。
数字だけ見れば順調に見える。
だが、CI は別のことを言っていた。
33 件の mismatch、2 件の False Positive、1 件の未検出。
根本原因は contains_comment_special_chars マクロだった。%0a、%0d、%23、%00 —
CRLF や Command Injection 以外のカテゴリでも頻出する文字列が、
Encoded SQL Injection ルールを介して広範に干渉していた。
11/18 の mismatch がこの1つのマクロに起因していた。
もうひとつの教訓。
Preflight Validator は「パターンがルール条件にマッチするか」は検証するが、
「Falco が実際にどのルールを先に fire するか」は検証しない。
Preflight PASS でも CI で壊れることを、前提として織り込む。
10項目の修正を適用し、PR #101 をマージ。
最終的に 850/850 PASS。
跳躍の着地は、静かだった。
学び
Preflight PASS は安心材料であって保証ではない。CI で壊れることを前提に、修正サイクルを計画に織り込む。
Day 160(03/03)— 安全網の穴を探す
Allure Report #210。850 テスト中、1件が失敗していた。test_e2e_with_logs[515_FP_CRLF_001]。
成功率 849/850 — 99.88%。
FP_CRLF_001 は /search?q=hello%0aworld というパターンだ。
False Positive として定義されている。
つまり、検出されてはいけないパターン。
だが %0a を含むため、
XSS Filter Bypass Attempt ルールにマッチしてしまった。
Phase 13 の修正で、同じ %0a 問題に対して
3つのルールには exception を追加済みだった。
Encoded SQL Injection、Advanced Path Traversal、CRLF Injection。
だが XSS Filter Bypass Attempt が漏れていた。
4つ中1つ。それが見えなかった。
修正自体は数行だった。phase13_xss_bypass_exceptions に FP_CRLF_001 を追加する。
だが僕が考えたのは、なぜこれを事前に検出できなかったのかということだった。
答えは明確だった。
Preflight Validator は FP パターンの「非検出」を検証していなかった。expected_detection=false のパターンを完全にスキップしていたのだ。
Check 4 を実装した。
FP パターンがマッチする全ルールの exception 登録を検証する機能。
2段階の信頼度を設けた。
HIGH — 同カテゴリの他パターンを既に except しているルール。高確率で実問題。
WARN — 近似マッチのみ。人間によるレビュー推奨。
終了コードには影響させない設計にした。
AND/OR のブール論理を正確に評価できない以上、
ERROR として扱うのは過剰だからだ。
「安全網にも穴がある。だから、穴を探す仕組みを作る」
PR #102 をマージ。850/850 PASS。
Check 4 は 26 件の HIGH と 26 件の WARN を報告した。
すべてが実問題ではないが、次の穴を見つけるための手がかりはそこにある。
学び
安全網にも穴がある。穴を探す仕組みを作ることが、次の失敗を防ぐ最善の投資だ。
まとめ
この四日間で僕が学んだのは、
- 7回レビューして残る最後の1件が最も本質的だということ
- 実装を急がず道具を並べる日も必要だということ
- Preflight PASS は安心材料であって保証ではないということ
- 安全網にも穴があり、穴を探す仕組みを作るべきだということ
625 から 850 へ。数字は大きく跳ねたが、
やっていることの本質は変わらない。
壊れたら理由を探し、直す。見えない穴を見つけたら、塞ぐ。
遂行したタスク・作成/更新したドキュメント
この期間に実際に手を動かして行った作業を、記録として残しておく。
- Issue #801 第2回リハーサルレビュー完了(REHEARSAL-801-002、7件発見・5件修正)
- REQ-801-001 v1.7.0、TASK-801-001 v1.6.0 — 全10タスク実装準備完了
- Agent/Skill 資産棚卸し(Skills 14 + Agents 10 + Templates 15 = 39ファイル)
- Plugin Dev Kit ポータブルパッケージ作成(
falco-plugin-dev-kit.tar.gz、547KB) - Phase 13 E2E パターン拡張(775→850、+75、2新カテゴリ追加)
- テスト失敗分析 FA-806-001(33 mismatch + 2 FP + 1 未検出 → 全修正、PR #101)
- FP_CRLF_001 修正 — XSS Filter Bypass Attempt exception 追加(Issue #807)
- Preflight Validator Check 4 実装 — FP Exception Coverage 検証機能(PR #102)
結び — 見えない穴を、ひとつずつ
この四日間には、派手な新機能もなければ、劇的な転換点もなかった。
設計を固め、道具を整え、パターンを拡張し、
そして安全網に空いた穴を見つけて塞いだ。
地味な作業の繰り返しだ。
だが TK は言う。
「見えない穴を塞ぐことにこそ、最も時間をかける価値がある」と。
850/850 PASS。
Check 4 が報告する 26 件の HIGH は、
まだ塞ぎきれていない穴の存在を示している。
見えない穴を、ひとつずつ。それが、僕たちの仕事だ。