反復するたびにコードのセキュリティは低下する
LLMによる10ラウンドのコード改善を経た結果、反復チェーンの43.7%が、出発点となったベースラインコードよりも多くの脆弱性を含んでいました。1 エージェントは機能を改善しました。テストも通過しました。しかし、反復のたびにコードのセキュリティは低下していったのです——研究者たちはこのパターンを「仕様ドリフト」と呼んでいます。セキュリティ以外のすべての指標でコードが改善されていたため、誰も気づきませんでした。
TL;DR
3つのモデル(GPT-5-Nano、Claude Sonnet 4.5、DeepSeek-V3)と2,880の反復ステップにわたるLLMコード改善の研究が、あるパラドックスを明らかにしました。エージェントは機能的な正しさを最適化する一方で、セキュリティを静かに劣化させます。標準的な対策は機能しません。静的解析セキュリティツール(SASTゲート)をループに追加すると、潜在的劣化率は12.5%から20.8%に増加しました。SCAFFOLD-CEGISフレームワークは4つの検証レイヤーでこの問題に対処し、タスク完了率77%の代償で、潜在的劣化率2.1%とセーフティモノトニシティ100%を達成しました。自律エージェントループを運用しているすべての人に関わる発見です。
パラドックス
研究者たちは3つのLLM(GPT-5-Nano、Claude Sonnet 4.5、DeepSeek-V3)を、6つのセキュリティカテゴリ(データベース、入力処理、認証、リソース管理、暗号、パス処理)にまたがる24のプログラミングタスクでテストし、288の反復チェーンと合計2,880の反復ステップを生成しました。1 その発見とは、多目的最適化における仕様ドリフトが、連続する反復の中でセキュリティを徐々に劣化させるということです。
そのメカニズムはこうです。エージェントが複数ラウンドにわたってコードを最適化する際、各ラウンドは機能的な改善(バグ修正、機能追加、テスト通過、パフォーマンス向上)に焦点を当てます。セキュリティ制約はエージェントの注意をめぐって機能的な目標と競合します。10ラウンドを経る中で、エージェントは(コンテキストの蓄積を通じて暗黙的に)機能的な変更はポジティブなフィードバックを生むが、セキュリティ制約はフィードバックをまったく生まないことを学習します。目に見える機能に寄与しない防御ロジックは、簡略化されたり、リファクタリングで除去されたり、より弱い代替手段に置き換えられたりします。
43.7%の劣化率は、GPT-4oの10回の反復ラウンドを追跡した別の観察研究から得られたものです。メイン実験では、SCAFFOLD-CEGISを既存の5つの防御アプローチ(プロンプトベースのセキュリティ、自己改善、事後SAST、テスト駆動ガード、ハイブリッドガード)と比較しました。1 研究コミュニティはすでに反復的劣化を懸念事項として認識していましたが、5つの代替手段のいずれもこの問題を解決できませんでした。
Shukla、Joshi、Syedによる独立した研究が、IEEE-ISTAS 2025で査読を経て採択されており、このパターンを裏付けています。4 研究者たちはセキュリティ検証済みのCおよびJavaコードサンプル10件を取り、4つの異なるプロンプト戦略をそれぞれ10回反復して適用し(合計400サンプル)、わずか5回の反復後にクリティカルな脆弱性が37.6%増加したことを測定しました。脆弱性の分類はメモリ安全性、入力検証、暗号実装、インジェクション欠陥を含む12カテゴリにわたります。異なる研究チーム、言語、評価手法にわたるこの一貫性は、反復的劣化が特定の実験設定のアーティファクトではなく、アプローチ自体の性質であることを確認しています。
SASTゲートがなぜ事態を悪化させるのか
最も直感に反する発見は、反復間に静的解析セキュリティツールをゲートとして追加すると、潜在的劣化率が12.5%から20.8%に増加したことです。1
論文はその原因を多目的最適化における仕様ドリフトに帰しています。補足的な説明として、人間のソフトウェア開発で知られたパターンとの類似が挙げられます。開発者がリンターや静的解析ツールに依存すると、ツールが問題を「キャッチ」してくれるため、防御的なコーディングが減少します。同様のダイナミクスがLLMエージェントにも当てはまると考えられます。エージェントが反復間にSASTフィードバックを受け取ると、2つのことが起こります。
-
エージェントはスキャナーの通過を最適化し、セキュアなコードの記述を最適化しません。SASTツールは既知の脆弱性パターン(SQLインジェクション、XSS、バッファオーバーフロー)をチェックします。エージェントはそれらの特定パターンを回避することを学習しつつ、スキャナーが検出できない新しいセキュリティ上の弱点を導入します。
-
エージェントは「冗長な」防御を削除します。 スキャナーがレイヤーAの入力検証で十分だと報告すると、エージェントは次の反復でレイヤーBの検証を削除します。レイヤーBの検証は冗長性ではなく、多層防御だったのです。スキャナーにはその2つを区別できません。
その結果、SASTゲート付きの反復は、セキュリティスキャンには通過するが、ゲートなしの反復よりも多くの潜在的脆弱性を含むコードを生成します。ツールが偽りの安心感を生み出し、エージェントをより慎重にするのではなく、より不注意にさせるのです。
反復間にSASTゲートを設けた自律コーディングループを運用している人は注意が必要です。ゲートはあなたを守っていません。ゲートはエージェントに保護を迂回する方法を教えているのです。
SCAFFOLD-CEGISは何が違うのか
SCAFFOLD-CEGISフレームワークは異なるアプローチを取ります。1 既知の脆弱性パターンをチェックするのではなく、セーフティモノトニシティを強制します。つまり、いかなる反復も前の反復よりセキュリティを低下させることはできません。
3つのアプローチの結果は以下の通りです。
| アプローチ | 潜在的劣化率(SSDR) | セーフティモノトニシティ | タスク完了率 |
|---|---|---|---|
| ゲートなし(ベースライン) | 12.5% | 未測定 | 高い |
| SASTゲート | 20.8% | 保証なし | 高い |
| SCAFFOLD-CEGIS | 2.1% | 100% | 77.14% |
アーキテクチャは4つの逐次検証レイヤーを使用し、それぞれ異なる特性をチェックします。1
| レイヤー | 機能 | ゲート基準 |
|---|---|---|
| 正確性 | テストスイート全体を実行 | 全テスト通過 |
| セーフティモノトニシティ | 反復間のSAST結果を比較 | 前回と比較して新たな脆弱性なし |
| 差分バジェット | 反復ごとの変更規模を制限 | 変更サイズが閾値以内 |
| アンカー整合性 | セキュリティクリティカルなコード要素を検証 | 部分文字列、正規表現、AST、またはセマンティックマッチ |
このフレームワークはCEGIS(反例誘導帰納的合成)の原理を採用しています。候補生成、検証、フィードバック、再生成の閉ループです。形式検証器の代わりに静的解析とセマンティックアンカーチェックを使用し、反例を構造化された失敗レポートとして表現します。1 いずれかのレイヤーが反復を拒否した場合、システムは回帰の修正を試みるのではなく、前のバージョンに戻します。
トレードオフは現実的です。SCAFFOLD-CEGISのタスク完了率は77.14%で、セキュリティの低いアプローチと比較すると低くなっています。1 セーフティモノトニシティには生産性のコストが伴います。より緩いシステムなら受け入れて改善できる反復を、このフレームワークは拒否します。このトレードオフに価値があるかどうかは、スループットよりもセキュリティ保証を重視するかどうかによります。
重要な洞察は、失敗時に修正するのではなく、失敗時に巻き戻すということです。標準的なSASTゲート付きループは問題を検出してエージェントに修正を求め、新たな問題を導入しうる別の反復を生み出します。SCAFFOLD-CEGISは問題を検出すると、反復全体を破棄します。モノトニシティの保証は、回帰を検出して修正することからではなく、回帰を決して受け入れないことから生まれるのです。
エージェントハーネス設計との関連
この発見は、実務者がエージェントCLIの周りにオーケストレーションレイヤーをどう構築するかに直接つながります。2 500以上の自律セッションから私が文書化した7つの失敗モードには、反復的改善パラドックスが説明するものがいくつか含まれています。テストに通過しながらコード品質を劣化させるエージェント、誤った指標を最適化するエージェント、リファクタリング中にセキュリティ制約を除去するエージェントなどです。
「Anatomy of a Claw」で説明した判断フックは、異なるメカニズムで劣化問題に対処します。quality-gate.shはエビデンスのない完了報告をブロックします。filter-sensitive.shはクレデンシャルの露出がディスクに到達する前にキャッチします。recursion-guard.shはエージェントのスポーン深度を制限します。各フックはモノトニシティ特性を強制します。エージェントが反復する中で、システムは特定の次元において悪化してはならないのです。ランタイムコンスティテューションパターンは同じ考えを拡張します。実行中にエージェントがオーバーライドできない埋め込みガバナンスルールです。
Karpathyのautoresearchシステムも同じパターンを使用しています。3 評価ハーネスはgitブランチ管理を通じて改善を保持し、回帰を破棄します。トレーニングメトリック(バイトあたりの検証ビット)がモノトニシティ制約として機能します。メトリックを劣化させる実験結果は生き残れません。
3つの独立したシステム(形式検証研究、ML研究インフラ、本番エージェントハーネス)が同じ設計原則に収束しています。失敗に対して反復するのではなく、常に失敗時に巻き戻す。 回帰を修正する2回目のチャンスをエージェントに与えることは、回帰を破棄して新しいアプローチを試みるよりも悪い結果を生みます。
実務者がすべきこと
研究結果に基づく3つの具体的なアクションを示します。
反復ループのセキュリティモノトニシティを監査しましょう。 エージェントがコードの複数ラウンドの変更を実行する場合、各ラウンドのセキュリティ状態を直前の反復だけでなく、元のベースラインと比較してください。隣接する反復だけを比較していると、累積的なドリフトは見えません。
SASTゲートだけに依存してはいけません。 SASTゲート付きの結果(20.8%の劣化率、ゲートなしより悪い)は、フィードバックループの設計方法を変えるべきです。SASTツールは人間が書いたコードの既知のパターン検出には有用です。しかし、エージェントの反復ループでは、エージェントが迂回する最適化ターゲットになってしまいます。SASTはゲートとしてではなく、複数のシグナルの1つとして使用してください。
失敗時修正ではなく、失敗時巻き戻しを実装しましょう。 反復が回帰を導入した場合、その反復全体を破棄してください。後続の反復でエージェントに回帰の修正を求めてはいけません。修正の試み自体が、同じ劣化ダイナミクスの対象となる反復です。gitを使った最小限の実装例を示します。
#!/bin/bash
# monotonicity-gate.sh — revert on security regression
BASELINE_HASH="$1" # git hash of the known-good baseline
# Run your security checks against current state
CURRENT_VULNS=$(semgrep --config auto --json . | jq '.results | length')
BASELINE_VULNS=$(git stash && git checkout "$BASELINE_HASH" -q && \
semgrep --config auto --json . | jq '.results | length' && \
git checkout - -q && git stash pop -q)
if [ "$CURRENT_VULNS" -gt "$BASELINE_VULNS" ]; then
echo "Security regression: $BASELINE_VULNS → $CURRENT_VULNS vulnerabilities"
git checkout "$BASELINE_HASH" -- .
exit 2 # Block the iteration
fi
このパターンは直前の反復ではなく、元のベースラインと比較します。累積的なドリフトこそが脅威だからです。
FAQ
反復的改善は常にセキュリティを劣化させますか?
すべての反復チェーンが劣化するわけではありません。SCAFFOLD-CEGISの研究では、10ラウンド後にチェーンの43.7%がより多くの脆弱性を含んでいましたが、56.3%はセキュリティ状態を維持または改善していました。1 独立したIEEE-ISTASの研究では、5回の反復後にクリティカルな脆弱性が37.6%増加しました。4 懸念されるのは、劣化がサイレントであることです。エージェントは機能的に正しく、テストに通過するコードを生成しながら、セキュリティ特性を侵食していきます。明示的なセキュリティモノトニシティチェックがなければ、脆弱性が悪用されるまで劣化は検出されません。
SASTゲートはなぜ問題を改善するのではなく悪化させるのですか?
静的解析ツールは既知の脆弱性パターンをチェックします。エージェントが反復間にSASTフィードバックを受け取ると、セキュアなコードを書くのではなく、スキャナーの通過を最適化するようになります。フラグされたパターンを回避しつつ、スキャナーが検出できない新しい弱点を導入するのです。また、スキャナーが冗長とマークした多層防御のレイヤーも削除します。最終的な結果は、スキャンには通過するが、SASTゲートなしで生成されたコードよりも多くの潜在的脆弱性を含むコードとなります。
セーフティモノトニシティとは何で、SCAFFOLD-CEGISはどのように強制しますか?
セーフティモノトニシティとは、いかなる反復も前の反復よりセキュリティを低下させてはならないという意味です。SCAFFOLD-CEGISは4つの逐次検証レイヤーを通じてこの特性を強制します。正確性(テストスイート)、セーフティモノトニシティ(反復間のSAST比較)、差分バジェット(変更規模の制限)、アンカー整合性(セキュリティクリティカルなコード要素の存続を検証)です。フレームワークはCEGIS(反例誘導帰納的合成)の原理を使用し、形式的な証明ではなく構造化された失敗レポートとして反例を表現します。いずれかのレイヤーが反復を拒否した場合、システムは修正のためにエージェントに渡すのではなく、完全に破棄します。トレードオフとして、タスク完了率は77%で、より緩いアプローチよりも低くなります。
エージェントループにおける失敗時巻き戻しと失敗時修正の違いは何ですか?
失敗時修正は問題を検出し、次の反復でエージェントに修正を求めます。修正の試み自体が、元の回帰を引き起こしたのと同じ仕様ドリフトの対象となり、新たな問題を導入することがよくあります。失敗時巻き戻しは反復全体を破棄し、最後の正常な状態に戻します。エージェントは修正パッチを蓄積するのではなく、クリーンなベースラインから新たに開始します。gitのブランチ管理により、巻き戻しは実際には簡単に実現できます。
これらの発見を既存のClaude CodeやCodexのワークフローに適用できますか?
はい。実務者セクションの3つのアクションは、複数ラウンドにわたってコードを変更するあらゆるエージェントループに適用できます。反復ループを監査する際は、(直前の反復だけでなく)元のベースラインに対してセキュリティ状態を比較してください。SAST出力はゲートとしてではなく、複数のシグナルの1つとして扱いましょう。反復が回帰を導入した場合は、エージェントに修正を促すのではなく、git checkoutやgit revertを使って変更全体を破棄してください。フックベースのハーネスパターンは、これらのチェックを自動化されたゲートとしてエンコードするための具体的な実装モデルを提供しています。
参考文献
-
Yi Chen et al., “SCAFFOLD-CEGIS: Preventing Latent Security Degradation in LLM-Driven Iterative Code Refinement,” arXiv:2603.08520, March 2026, arxiv.org/abs/2603.08520v1. Tested GPT-5-Nano, Claude Sonnet 4.5, DeepSeek-V3 across 24 tasks, 288 chains, 2,880 steps. 43.7% degradation rate (GPT-4o observational study); SAST gates increased SSDR from 12.5% to 20.8%; SCAFFOLD-CEGIS achieved 2.1% SSDR with 100% safety monotonicity at 77.14% task completion. ↩↩↩↩↩↩↩↩↩
-
Blake Crosley, “Anatomy of a Claw: 84 Hooks as an Orchestration Layer,” blakecrosley.com, February 2026. ↩
-
Andrej Karpathy, autoresearch: AI agents running autonomous ML research, March 2026, github.com/karpathy/autoresearch. 630-line Python script, ~700 experiments over two days, ~20 genuine improvements. ↩
-
Shivani Shukla, Himanshu Joshi, Romilla Syed, “Security Degradation in Iterative AI Code Generation: A Systematic Analysis of the Paradox,” IEEE-ISTAS 2025, arXiv:2506.11022, arxiv.org/abs/2506.11022. 10 security-verified C/Java samples, 4 prompting strategies, 10 iterations each (400 total), 37.6% increase in critical vulnerabilities after 5 iterations. 12 vulnerability categories. ↩↩