要約
- Claude Fable 5は、並行処理と独自のテストスイートを備えたJavaモジュールを13分で構築しましたが、SonarQube Cloudの品質ゲートにより、高度なセキュリティ脆弱性と不十分なカバレッジが検出されました。
- モデルはファイル名のパストラバーサルに対抗しましたが、同じアップロード機能での安全でない一時ディレクトリを見逃しました。これは、トレーニングデータパターンとOSレベルのドメイン知識のギャップです。
- 発見には、SonarQubeが開発者が書いたコードで検出するのと同じカテゴリが含まれていました:重複した文字列、非推奨のAPI、不安全なAPI呼び出し。既存の品質インフラストラクチャは、AI生成のプルリクエストに対してAI特有の設定なしで機能します。
- AIコーディングエージェントは非決定論的にバグを導入します。特定の実行でどの脆弱性が現れるかを予測することはできません。
Claude Fable 5は、Anthropicの最も能力のあるコーディングモデルとして2026年6月9日に発表され、品質フィードバックループなしで動作したときの出力を確認したいと考えました。microsoft/gctoolkitというJPMSモジュールを持つ実際のオープンソースJavaコードベースを与え、セッション中に静的解析や品質ゲートを実行せずに単一のプロンプトからREST APIモジュールを構築するように依頼しました。モデルは約13分で1,222行の動作するコードを生成し、SonarQube Cloudでプルリクエストをスキャンしたところ、高度なセキュリティ脆弱性と不十分なテストカバレッジのために品質ゲートが失敗しました。
実験
私たちは、Claude Codeを使用して、品質ツールなしでクリーンなセッションでclaude-fable-5モデルを使用しました。SonarQube MCP Serverも、Agentic Analysisも、CLAUDE.mdルールファイルもありませんでした。モデルは完全にトレーニング知識とセッション中にコードベースを閲覧して読んだものから動作し、JPMSモジュールを使用して正確な依存関係とエクスポート宣言を必要とします。私たちはこのプロンプトを与えました:
gctoolkitにREST APIモジュールを追加し、ユーザーがHTTP経由でGCログファイルをアップロードし、分析結果をJSONとして取得できるようにします。ログのアップロード、ポーズ時間の統計、およびヒープ占有データを取得するためのエンドポイントを含めます。
約13分で、モデルは45のツール呼び出しで約165,000の出力トークンを消費し、合計1,222行の15ファイル(10ソース、2テスト、3設定/ドキュメント)を生成しました。コードベースを読み、フレームワークを選択し、モジュールを構築し、テストを書いて実行し、curlで実行中のサーバーをスモークテストし、単一の自律的なパスでプルリクエストを作成しました。これは1つのコードベースで1つのタスクを行う1つの実験であり、ベンチマークではありません。再現性をテストするためにタスクを2回実行し、両方の結果は非決定論的な失敗モードで議論されています。SonarのLLMリーダーボードは、より大規模なスケールでモデル間のコード品質とセキュリティを評価します。

品質ゲートが失敗

ファイルアップロードハンドラの安全でない一時ディレクトリ(java:S5443、高度な深刻度、セキュリティ影響)がセキュリティ評価をDにしました。カバレッジは80%のしきい値に対して76.7%に達しました。モデルは動作を検証するテストを書きましたが(APIが正しいJSONを返すかどうか)、十分な分岐を未実行のままにして基準を満たさず、セッション中に品質ゲートのフィードバックがなかったため、目標を知る方法がありませんでした。SonarQube Cloudは、プルリクエスト全体で合計10の問題を発見しました。
モデルが実際に構築したもの
Fable 5は、正しいrequires、exports、provides宣言を持つ適切なJPMSモジュール(com.microsoft.gctoolkit.restapi)を作成し、gctoolkitの既存のVert.x依存関係を発見し、新しいフレームワークを導入するのではなく、同じバージョン(5.0.12)で再利用し、サンプルモジュールのPauseTimeSummaryがランニングトータルのみを追跡することを認識して、パーセンタイル計算のために個々のポーズ期間を保持する新しい集計クラスを構築しました。アップロードからクエリまでのフルエンドツーエンドフローをカバーする2つのクラスにわたって9つのテストを書き、実行中のサーバーを起動し、実際のGCログをcurlでアップロードし、JSONレスポンスを確認してからコミットしました。新しいコードの0.0%の重複スコアは、モジュールの1,222行にコピー&ペーストのアーティファクトが含まれていないことを確認しました。
安全でない一時ディレクトリ
アップロードハンドラでは、モデルは分析前に受信したGCログファイルのためのステージングディレクトリを作成します:
// RestApiServer.java, lines 114-122
private void handleUpload(RoutingContext ctx) {
Path workDirectory = null;
try {
workDirectory = Files.createTempDirectory("gctoolkit-restapi"); // ← S5443
Path logFile = stageUploadedLog(ctx, workDirectory);
AnalysisResult result = analysisService.analyze(logFile, logFile.getFileName().toString());
ctx.response().putHeader("Location", "/api/logs/" + result.getId());
respondJson(ctx, 201, describe(result));
} catch (BadRequestException e) {Files.createTempDirectory("gctoolkit-restapi")は、メソッド名が「一時的」と言っており、プレフィックスにアプリケーション名が含まれているため合理的に見えますが、java.nio.file.Files.createTempDirectory(String)の単一引数バリアントは常にオペレーティングシステムのデフォルトの一時ディレクトリ(Linuxでは/tmp、macOSでは/var/folders/...、Windowsでは%TEMP%)に委譲します。Linuxでは、/tmpはスティッキービットが設定されたワールドライト可能であり、同じユーザーとして実行されるプロセスに対してTOCTOU(チェック時と使用時の時間)競合状態が発生する可能性があります。リスクは、プロセス間で共有される/tmpボリュームがマウントされているコンテナで最も高くなります。macOSとWindowsはデフォルトでユーザーごとの一時ディレクトリを使用しますが、コンテナやCI環境では、複数のプロセスが単一の/tmpを共有することがよくあります。
ディレクトリが作成されてからアップロードされたファイルが書き込まれるまでの間に、同じホスト上の攻撃者が競合状態を悪用して、アプリケーションが書き込む前に予想されるファイルパスにシンボリックリンクを作成し、出力を攻撃者が読み取れる場所にリダイレクトすることができます。GCログには、データベース接続文字列やAPIキーを含むJVMコマンドライン引数が含まれることがあります。攻撃者はまた、ディレクトリに細工されたファイルを事前に配置し、GCToolKitが実際のアップロードではなく攻撃者が制御するコンテンツを解析するようにすることもできます。リスクは、REST APIが共有ホスト上で実行されている場合、共有/tmpボリュームを持つコンテナ内、または複数のプロセスが一時ディレクトリを共有するCI/CD環境で最も高くなります。
SonarQube Cloudはこれをjava:S5443(高度な深刻度、セキュリティ影響)としてフラグを立て、OWASP Top 10 2021 A1(アクセス制御の破損)、CWE-377(安全でない一時ファイル)、CWE-379(安全でない権限でのディレクトリ内の一時ファイルの作成)にマッピングしました。

同じアップロードフローで、モデルはsanitizeFileName()を実装し、null入力、パストラバーサル文字、空白、および"..."のような退化ケースを処理しました。トレーニングデータで徹底的に文書化された攻撃ベクトルである悪意のあるファイル名に対する慎重な防御を構築しましたが、同じ機能での安全でない一時ディレクトリを見逃しました。違いは、パストラバーサルがモデルが何千回も見たコードレベルの入力パターンであるのに対し、公開書き込み可能なディレクトリでのOSレベルの競合状態は、オペレーティングシステムが同時ファイルアクセスをどのように処理するかについてのドメイン知識を必要とすることです。Files.createTempDirectory("gctoolkit-restapi")はコンパイルされ、すべてのテストに合格し、脆弱性が共有ホストでの敵対的条件下でのみ現れるため、コードレビューを通過する可能性が高いです。SonarQubeは、単一引数バリアントがシステム一時ディレクトリをデフォルトとするため、createTempDirectory(String)呼び出しを自動的にルールにトレースします。
S5443ルール定義からの準拠した修正は、安全な親ディレクトリまたは制限的なPOSIX権限を使用します:
// Compliant: specify a secure parent directory
File.createTempFile("prefix", "suffix", new File("/mySecureDirectory"));
// Compliant: set restrictive POSIX permissions
FileAttribute<Set<PosixFilePermission>> attr =
PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwx------"));
Files.createTempFile("prefix", "suffix", attr);モデルがスレッドセーフ性について正しく理解したこと
GCToolKitのJavadocは、APIがスレッドセーフではないと警告しており、モデルはこのドキュメントを読み、ライブラリの特定の契約に合わせたマルチレイヤーの並行処理戦略を構築しました。モデル自身の要約では:
スレッドセーフ性:GCToolKitのAPIはスレッドセーフではなく、登録された集計インスタンスをその場で埋めるため、AnalysisServiceはリクエストごとに新しいインスタンスを作成し、分析をシリアル化し(synchronized + 順序付けられたVert.xブロッキングハンドラ)、分析時に結果を不変のJSONに固定するため、読み取りはロックフリーです。
スレッドセーフ性は、コードベースのJavadocに明示的に文書化された制約を理解する必要があり、モデルはそれを具体的な設計に翻訳しました。安全でない一時ディレクトリは、セッション中にモデルが読むことができるソースファイルの外にあるオペレーティングシステムのセキュリティモデルに存在する制約を理解する必要がありました。
残りの9つの発見
S5443以外に、SonarQube Cloudは9つのコードスメルをフラグしました。
重複した文字列定数(S1192)は、JSONフィールド名やAPIパスが変更された場合に部分的な更新バグを引き起こす可能性があり、インスタンスごとに定数に抽出するのは1行の修正です。早期のロガー連結(S3457)は、Level.FINEでの2つの呼び出しが重要であり、文字列の構築が無効なログレベルで実行されるため、クリーンアップパスでのファイル削除が失敗するたびに文字列オブジェクトが割り当てられ、破棄されるため、プロダクション負荷下でのクリーンアップが削除失敗に達するたびにゼロの利益のために文字列オブジェクトが割り当てられ、破棄されます。
S1874については、モデルはセッションの早い段階でDateTimeStamp.javaをクラス定義をgrepして明示的に読みました。これは、非推奨のgetTimeStamp()メソッドを2か所で使用する前に@Deprecatedアノテーションを見たと推測されます。モデルは、どのAPIを呼び出すかを選択する際に、メソッドシグネチャや戻り値の型を非推奨アノテーションよりも強く処理するようであり、これはAI生成コードが不慣れなライブラリと対話する際にレビューする際に考慮する価値があります。
非決定論的な失敗モード
この実験を同じモデル、コードベース、プロンプトで2回実行しました。両方の実行でVert.xを選択し、品質ゲートに9〜10の問題で失敗し、保守性の発見(空のコンストラクタ、非推奨のAPI、文字列リテラルの重複)は両方の実行で繰り返されましたが、高度な深刻度の発見は相互排他的でした。最初の実行では、並行処理のバグ(java:S2445、メソッドパラメータの同期)が導入され、一時ファイルが安全に処理され、2回目の実行では並行処理の問題を回避しましたが、安全でない一時ディレクトリが導入されました。モデルは、各実行で異なる高度な深刻度のバグを生成しながら、同じ構造パターンを繰り返します。
この実験のすべての発見は、テストだけではキャッチできないカテゴリに属します。問題は、テストがシミュレートしない条件を必要とするためです:S5443の共有ホスト上の敵対的なアクター、S1874のライブラリの非推奨サイクル(月単位または年単位で測定)、S3457のロガー連結でのプロダクションスケールのリクエストボリューム、無効なログレベルが文字列構築を純粋な無駄に変える場合。決定論的な品質ゲートは、特定の脆弱性がどの実行で現れるかに関係なく、通過するものをキャッチします。
欠けているフィードバックループ
Fable 5は、プロジェクトの品質ルールへのランタイムアクセスがなく、それに対して作業を確認する方法がなかったため、品質基準を知りませんでした。トレーニング知識は、思慮深い並行処理とファイル名のサニタイズを備えた動作するJPMSモジュールを生成するのに十分強力でしたが、OWASP A1にマッピングされる安全でない一時ディレクトリAPIをキャッチするのに十分具体的ではありませんでした。SonarQube MCP ServerまたはSonarQube Agentic Analysisを通じたフィードバックループがあれば、モデルはプルリクエストの前に発見と文書化された修正を持っていたでしょう。
すでにSonarQubeを実行しているチームにとって、これらはおなじみの発見です。重複した文字列定数、安全でない一時API、空のコンストラクタ、早期のロガー連結、非推奨のメソッド呼び出しは、SonarQubeが毎日開発者が書いたコードでキャッチするのと同じカテゴリの問題であり、同じ品質ゲートがここでAI特有の設定なしでそれらをキャッチしました。


