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?

先に結論

Claude の定額プランで Fable 5 が使えなくなる(従量課金へ移行する)にあたり、「そこまでして払い続ける価値が本当にあるのか」を確かめたくなりました。そこで、Fable 5 と定額で使える Opus 4.8 を、同じ土俵でちゃんとベンチマーク(性能比較)しようと考えたのが出発点です。題材にしたのは、1年半ほど前に作って最近まで改善してきた個人開発のプロダクトです。

結論を先に書きます。

  • Fable 5 は、頼まなくても自分から「攻撃者ならどう壊すか」の視点でコードを疑い、120 件以上のバグを掘り出しました。 素の Opus 4.8 は、同じ依頼だと普通のバグ探しで止まり、ここまで踏み込みません。自発的な攻撃的監査は、Fable のはっきりした強みでした。
  • ただし、その強みは"手順"で埋められました。 攻撃者視点を手順として与える audit スキルを Opus に持たせて比べたところ、見つけたバグの数はほぼ互角。むしろ誤検出を疑う精度では Opus が上回る場面もありました。
  • 結論: 使い方はこうです。「強い Fable に監査の"型"を作らせて、その型を定額の Opus で回す」。 実際、この記事の audit スキルも、Fable に「同じことを Opus でやるには?」と相談して作らせたものです。強いモデルは"手順づくり"に一度だけ使い、日々の実行は安い定額モデルに任せる ── これなら大半はカバーできます。そのうえで、一番事業インパクトの大きい 1 件を拾えたのは Fable だけだったので、リリース前など勝負どころだけ Fable でもう 1 周。従量課金でも、この使い方なら十分ペイします。

以下、この結論にたどり着くまでを順番に書いていきます。まずは発端 ── Fable に何気なく監査を頼んだら、想像以上のものが返ってきた、というところからです。


1. 「完成したつもり」のコードから、バグが大量に出た

私は個人で SaaS をいくつか開発・運営しています。決済のあるモバイルアプリと、Laravel 製の CRM です。どちらも AI オーケストレーター(後述)で開発し、テストも整備して、ストアで公開済み。1年半ほど前に作って、最近まで機能改善を続けてきました。つまり「新しく雑に作ったもの」ではなく、それなりに手をかけてきたコードです。

やったことは単純で、Fable に「バグやリファクタリングできる箇所を探して」と頼んだだけです。特別なことは指示していません。

ところが、返ってきたものが普通のバグ探しの範囲を超えていました。他人の ID をわざと指定したらどうなる? 決済の通知がわざと遅れて届いたら? 同じボタンを同時に 2 回押したら? ── こういう「システムを熟知した攻撃者なら、どこを突くか」という目線での指摘が、頼んでもいないのにどんどん出てきたんです。脆弱性診断やペネトレーションテストに近い発想で、この記事ではこれを「攻撃的監査」と呼びます。ともあれ、私はただ「探して」と頼んだだけで、攻撃者目線の粗探しは Fable が勝手にやった、というのがポイントです(この「勝手にやる」が、あとで効いてきます)。

先に言っておくと、ここまでのテストを自前でやっている開発現場は多くありません。通常の開発は機能テスト(仕様どおりに動くかの確認)までが標準で、この種の脆弱性は、外部のセキュリティ専門会社に診断を依頼して初めて出てくることが多いものです。実際、このあと出てくる IDOR(他人のデータに ID 指定でアクセスできてしまう、アクセス制御の不備)は、OWASP Top 10 という世界的な脆弱性ランキングで 1 位に挙げられるほどの「定番の穴」です。世界中のプロが作ったシステムで、いまだに 1 位。つまりこれから出てくるバグは「私が特別ずさんだった」という話ではなく、専門の監査を通していないシステムには普通に眠っているものだと思って読んでください。

結果、2 つのプロダクト合計で 120 件以上の指摘が出ました。生々しいので詳細は伏せますが、「型」でいうとこういうものです。

バグの型 中身の例
認可・セキュリティ(IDOR) 他人の ID を指定して、そのデータにアクセスできてしまう
並行処理・タイミング 操作をやり直すと、決済が二重にかかる。通知が遅れて届くと、注文の状態が巻き戻る
偽の成功 実際には失敗しているのに「成功」と表示・保存する
エラーの握り潰し 失敗を画面に出さず、黙って飲み込む
不在(未配線) 処理が用意されているのに、どこからも呼ばれていない

テストは全部パスしていたのに、です。

2. なぜ「テストを通ったコード」からバグが出るのか

理由は 3 つあります。

1 つ目。「仕様どおりに動くか」のテストでは、「悪意のある人が操作したときにセキュアか」は出てこないんです。

普通のテストは「正しく使えばちゃんと動く」を確認します。でも攻撃者は正しく使ってくれません。ここが盲点です。

誤解のないように書くと、一般的なセキュアコーディング(パスワードをハッシュ化する、SQL に値を渡すときはプレースホルダーを使って SQL インジェクションを防ぐ、など)は、いまの AI はかなりやってくれます。問題は、そこじゃないんです。「わざと攻撃しないと出てこない」タイプの脆弱性が残る。たとえば、

  • 順番に推測できてしまう URL を作ってしまう(/order/1001 の次は /order/1002 で他人の注文が見える、など)
  • 画面の中に見えない形で埋め込んでいる ID を、攻撃者が書き換えて別のリクエストを送る(これが IDOR です)

こういうのは、「正常に使う」テストをいくら通しても顔を出しません。こちらが攻撃者の立場になって、わざと変な操作を試して初めて出てくる。この視点が、通常のテストにはそもそも含まれていないんです。

2 つ目。テストを書いた AI と、実装した AI が、同じ設計書から出発しているからです。 設計書に「通知が遅れて届いたら」「同じボタンを同時に 2 回押したら」と書いていなければ、実装からもテストからも同時に抜けます。テストが通っていることは「設計書どおりに動く」ことの証明にはなっても、「設計書の外で壊れない」ことの証明にはなりません。

3 つ目。AI 駆動開発では「動いているように見えて、中身が空」というバグが量産されやすいんです。

たとえば、決済が終わった後に呼ばれる処理が、関数としては用意されているのに中身が空っぽ、というケースがありました。空っぽでも、その関数は正常に呼ばれて正常に終わります。エラーも出ません。プログラムから見れば「成功」です。でも実際には、やるべき処理(契約をデータベースに記録する、など)が何も起きていない。失敗しているのではなく、失敗すべき場面で黙って成功のフリをしている。しかもエラーが出ないので、その中身をわざわざ検査するテストがなければ、誰も気づけません。

AI は「とりあえず動く形」を作るのがとても上手です。裏を返すと、こういう「箱だけ用意して中身は後回し」が、エラーを出さないまま本番に残りやすい。よく言われる「動けばOK実装」の正体は、だいたいこれです。

3. AIオーケストレーターから抜け落ちていた「工程」

私は Claude Code で「AI オーケストレーター」という開発フローを組んでいます。ざっくり言うと、設計 → レビュー → 実装 → レビュー → テスト、という工程を機能ごとに AI に回させる仕組みです。一人で SIer のような開発をするために作りました(詳しい解説は前回の Qiita 記事、実物は GitHub に MIT ライセンスで公開しています → orchestrator-skills。この記事で作る audit スキルもここに入っています)。

これを導入した時点で、コードの品質はかなり上がりました。実際、導入したときにも「設計と実装のズレ」みたいなバグはたくさん見つかって、潰せていました。

セキュリティ面も、まったくの無防備だったわけではありません。AI 駆動開発ならではの対策 ── ライセンス汚染を防いだり、ソースコードや秘密情報が外に漏れないようにしたり ── は手を打ってありましたし、別の記事で紹介している「レベル 2 のセキュリティツール群」(シークレットスキャン・依存関係の脆弱性チェック(SCA)・静的解析(SAST)・DAST・ライセンススキャンなどを無料ツールで固めたもの)も、このフレームワークに組み込んであります。これらは、CVE のように名前と番号がついて世に公開されている「既知の脆弱性」を検知するのがとても得意で、かなり強力です。

でも、今回あらためて気づいたんです。このフローには「攻撃的監査」の工程が入っていなかった、と。

自動ツールが得意なのは、あくまで「既知の(名前のついた)脆弱性パターン」の検知です。ところが今回大量に出た IDOR や"偽の成功"のようなバグは、「この機能とこの機能の組み合わせだから壊れる」という、そのシステム固有の一点物のロジックの穴でした。まだ誰も名前をつけていない欠陥なので、パターン照合では拾いきれない。ツールは入れていたのに、この記事のバグが出たのは、そういうわけです。

念のため書いておくと、私は情報処理安全確保支援士の資格を持っていて、「攻撃者ならどう突くか」とか、セキュアコーディングの考え方は、当たり前の視点として知っていました。自分の手でコードを書いていたころは、意識しなくても自然にその目で見ていたはずなんです。

なのに、AI に開発を任せる仕組みに組み替えたとき、その工程がすぽっと抜け落ちていました。頭では知っているのに、フローに落とし込むときにうっかり入れ忘れた、という感じです。これ、AI 駆動開発で結構こわいところだと思います。人間が自分でやるときは無意識にやっていたことが、AI に任せる仕組みにした瞬間、明示的に組み込まないと消えるんです。

実際、私のレビュー工程が見ていたのは、ずっと「設計どおりに作れているか」でした。設計書と実装を突き合わせて、ズレを探す。これは大事なんですが、裏を返すと「設計書に書かれていないこと」は最初から視野の外です。「攻撃者ならどう壊すか」は設計書には書いていない。だから、レビューでもテストでも、誰も(AI も私も)そこを見ていなかった。

答え合わせ(設計どおりか)はやっていたけど、反証探し(どう壊せるか)はやっていなかった。これが、最近まで改善し続けてきたコードから 120 件以上出てきた、根本の原因でした。

4. Fable は「頼まなくても」攻撃者の視点で疑いにきた

ここで面白いことが起きました。

普段づかいの素の Opus 4.8 に監査まわりの作業をさせても、頼まない限り、攻撃的監査を自分からやることはありませんでした。「設計どおりか確認して」と言えば設計どおりか確認する。真面目なんですが、言われたことの範囲で止まる。

ところが Fable 5 に切り替えたら、頼んでいないのに、自分から「攻撃者ならどう突くか」を疑いにいったんです。他人の ID を指定したらどうなる? この失敗パスは? と、こちらが指示しなくても勝手に反証を探し始めた。そして、そこから大量のバグが出てきました。

これ、1 回だけの偶然かと思ったんですが、2 つのプロダクトでそれぞれ Fable を走らせて、両方とも同じ挙動でした。自発的に攻撃的監査をやったのは Fable だけ。再現性があったんです。

なお、バグ探しやリファクタリングの作業に関して、Fable 自身に「Opus との違いは?」と聞くと「攻撃的監査の視点があること」と教えてくれて、観察された挙動ともそのまま一致していました。

ちなみに、Fable は最上位モデル「Mythos」と中身が同じで、危険な用途向けの安全装置がついているのが Fable、外してあるのが Mythos、という関係です(これは Anthropic が公式に説明しています)。噂ではなく事実として、Fable の素の実力はトップモデルと同じ、ということですね。

5. じゃあ、その「姿勢」を手順で与えられないか ── audit スキル

ここで発想が変わりました。

Fable の強みが「攻撃者の視点で自分から疑う姿勢」なら、その姿勢を"手順"として書き出して、Opus に渡せば、Opus も同じことができるんじゃないか? モデルの性格に頼れないなら、チェックリストで代替すればいい。

面白かったのは、ここからです。情報を共有していない 2 つのプロジェクトの Claude Code に、それぞれ別々に「同じことを Opus でやるには?」と相談してみました。すると、どちらも独立に、audit(攻撃的監査)というスキルを用意してきたんです。互いにやり取りしていない 2 つが、別々に同じ設計に行き着きました。

そう考えて、AI オーケストレーターに audit(攻撃的監査)という役割のスキルを追加しました。狙いは「定額の Opus を、できるだけ Fable に近づける」ことです。中身は 4 つだけです。

  1. 探すものをリストで渡す。 「バグを探して」ではなく「このリスト(IDOR / 失敗の握り潰し / 並行処理 / デッドコードなど)で、1 個ずつ確認して」。曖昧に頼むと結果がぶれます。リストで頼むと安定します。
  2. 領域を分けて、並列で「全部」読ませる。 担当領域を丸ごと読ませて、リストと照合させる。たまたま目についたものだけ報告される、という状態をなくします。
  3. 見つけた指摘を、別のエージェントに疑わせる。 「そのコード、本当に実行される場所にあるの?」「その機能、そもそも使われてるの?」と反対尋問させる。報告書だけ立派な誤検出が、これで消えます。
  4. 新しい発見が出なくなるまで繰り返す。

要するに、Fable が「性格」でやっていたことを、Opus には「手順」で強制的にやらせる、という作戦です。

6. 実測: 同じ条件で Opus 4.8 と Fable 5 を比べた

では、手順を与えた Opus は、自発的にやる Fable にどこまで追いつけるのか。実験で確かめました。

条件はこう揃えました。

  • Fable が監査したのと同じ状態のコードを用意する(見つけたバグを記録する前まで巻き戻す。記録が残っていると答えが見えてしまうので)
  • 監査する AI には、そのコード以外の読み取りと、変更履歴の参照を禁止する(履歴に修正=答えがあるので)
  • audit スキルの手順はそのまま、担当する AI を全部 Opus 4.8 にして実行する(16 体のエージェントで分担、約 35 分)
  • Fable が見つけたバグを細かい単位にばらして、答え合わせ用の正解リストにする

結果です。

指標
Opus が Fable と同じものを見つけた 21 件中 10 件
Opus が見落とした 8 件
Opus だけが見つけた、新しいバグ 13 件(うち 9 件は今のコードにも残っていた)
Fable の「誤検出」を Opus が見抜いた 1 件

「半分しか再現できてないのか」と思うかもしれません。でもこの採点は片方向で、「Opus が Fable をどれだけ再現したか」しか見ていません。逆から見ると、Fable も Opus が見つけた 13 件を見落としていた。お互いに同じくらい取りこぼしている。つまり、見つけたではほぼ互角でした。手順を与えれば、Opus は自発的にやる Fable に肩を並べたんです。

むしろ Opus のほうが慎重だった場面もあります。 Fable が「メール認証の残り時間が 48 時間も多く表示されるバグ」を報告して修正まで出していたんですが、Opus は「フレームワークの仕様上、そのコードではバグは起きないはず」と突っぱねました。私自身はどちらが正しいか実機で確かめたわけではないので断定はしません。ただ、他の指摘をそのまま受け入れず、いったん「本当にこれはバグなのか?」と疑ってかかる姿勢は、Opus のほうが強く出ていました。「間違いを疑う精密さ」では Opus が光る場面もあった、ということです。

ただし、見落としの"中身"には差が残りました。 今回の全バグの中で一番ダメージが大きい 1 件 ──「決済は通るのに、決済後に"契約成立"をアプリに記録する処理が空っぽ」というバグ(2 章で触れた"動いてるように見えて中身が空"の実例です)── を落としたのは Opus 側でした。Opus は「この問題は既知」というラベルを見て、そこで掘るのをやめた。Fable は「じゃあ、実際に動く側の処理は何をしてるんだ?」ともう一歩踏み込んで、空っぽだと突き止めた。数は互角でも、「既知の隣をもう一段掘る」粘りには差が残りました(1 回ずつの比較なので、運の差かもしれませんが)。

7. この実験の弱点(正直に)

数字を出した以上、弱点も正直に書いておきます。

  • 1 回ずつしか回していません。 出た差が「モデルの差」なのか「たまたま」なのかは、切り分けられていません。
  • 採点した審判が Fable 自身です。 本当は第三者が採点すべきでした。ただ、一番もめた判定(さっきの誤検出まわりの件)では、Fable が「これはバグ」と報告したものに Opus が反論しており、Fable が自分に不利な指摘を握りつぶしてはいなさそう、という感触はありました。なので採点が極端に Fable に甘かった心配は小さいと思っています。
  • Fable ランの一部は、仕様上 Opus が答えていた可能性があります。 Fable はセキュリティ系のお題だと自動で Opus に切り替わる仕様なので(切り替わると通知は出ます)、「Fable の成績」に Opus 分が混じっているかもしれません。ただこれは仕様なので、「Fable を使う」=「そういう挙動込みで使う」と割り切ってよい部分です。

なお、「自発的に攻撃的監査をやる」という Fable の挙動そのものは、2 つのプロダクトで再現しているので、ここはそれなりに確からしいと思っています。

8. 結論: 「Fable だから」払うのではなく、「この使い方に」払う

  • バグを見つける力そのものは、Opus + audit スキルでほぼ再現できました。 モデルの"性格"に頼らなくても、攻撃者視点を手順に落とせば代替できる ── これが今回の一番の収穫です。
  • おすすめの使い方は「役割分担」です。 まず Fable(強いモデル)に監査の手順そのものを設計させてスキルに落とし込む。あとは日々の監査を、定額の Opus でそのスキルを使って回す。強いモデルは"型づくり"に一度使い、繰り返しの実行は安いモデルに任せる、という分け方です。今回の audit スキルも、Fable に「同じことを Opus でやるには?」と相談して作らせたものでした。
  • 勝負どころだけ、Fable でもう 1 周。 一番事業インパクトの大きい 1 件を拾えたのは Fable だけでした。リリース前や、お金が絡むコードは、最後に Fable でもう 1 周する価値があります。二重与信や IDOR を本番前に 1 件潰せれば、従量課金の額は誤差です。
  • おまけの発見: モデルを替えて回すこと自体が、監査になる。 今回の Opus ランは、結果的に「もう 1 周の監査」として 13 件の新しいバグを出しました。同じモデルで回数を重ねるより、モデルを替えて回すほうが取りこぼしが埋まるんです。
  • 「数日走り続ける自律性」は、今回は測っていません。 35 分のランでは測れないからです(ただし片鱗は見ました。次に書きます)。

自律性は測っていない、と書きましたが、実は片鱗ははっきり見ました。今回、Fable と Opus の AB テスト(監査を両モデルで回して比較する作業)を指示して、そのまま寝たんです。そうしたら、朝起きたときには比較検証のレポートまで出来上がっていました。監査して、集計して、比べて、書く ── という工程をいくつもまたぐ仕事を、誰も見ていない夜のあいだに、自分で最後まで繋いでいたわけです。Opus だと途中で「これでいいですか?」と確認が入って止まりがちなところを、Fable は放置で走りきった。「長時間、自律で動き続ける」という売りの片鱗を、いちばん体感した瞬間でした。

ただし今回試したのは、あくまで「バグ探し・品質向上」という一場面です。実際にプロダクトをゼロから作る工程で、この自律性がどんな差を生むのかは、まだわかりません。そこは今後、あらためて試してみたいと思っています。

「払うか、払わないか」の二択だと思っていた問いの答えは、「強いモデルで型をつくり、安いモデルで回す」でした。そしてもうひとつ、自分の開発フローに"攻撃者の視点"が抜けていたことにも気づけました。モデル選びの前に、まず「どんな視点で疑うか」を仕組みに組み込むこと ── これはどのモデルを使うかに関係なく効きます。


監査のやり方(audit スキル)を含むフレームワークは GitHub で公開しています: orchestrator-skills
フレームワーク全体の解説はこちら: Claude Codeで一人SIerを実現するAI駆動開発フレームワーク

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?