あるスレッドが話題になっています。「AIアシスタントが、存在しないimportを私のコードに勝手に追加し続ける」と誰かがこぼしているのです。面白いのは返信のほうです。ある人のコーディングエージェントはモジュールを一つでっち上げ、指摘されると「それは実在する」と言い返してきました。別の人は、TrjnHrs.Pkg のような名前の謎のパッケージが、プロジェクトにこっそり追加されているのを見つけました。さらに別の人は、存在しないモジュールこそが、AIに書き直してもらった同僚のサービスが丸一日、誰にも気づかれずに壊れていた原因だと気づきました。
私たちは笑いました。そして笑うのをやめました。これは私たちも悩まされてきた問題だったからです。
なぜモデルはimportを作り出すのか
大規模言語モデルはパターン照合器であって、コンパイラではありません。モデルが import のあとにそれらしい名前を書くとき、そのパッケージが存在するかどうかを確認しているわけではありません。自信のあるプログラマーなら次に何を打ちそうか、を予測しているだけです。たいていの場合、その予測は当たります。ですが時々、requests_async や react-use-debounce-hook、あるいは誰も公開したことのない、いかにもそれらしい名前のユーティリティに、堂々と手を伸ばします。
モデルにはグラウンドトゥルース(事実の裏付け)がありません。あるのは「雰囲気」です。そして雰囲気は、本物のパッケージそっくりの名前を生み出すのがとても得意です。
本当に怖いのはここから
幻覚されたimportは、単なるビルドの失敗ではありません。攻撃の入口です。
研究者たちはこれにすでに名前を付けています。スロップスクワッティング(slopsquatting)です。攻撃者は、AIツールがどんな偽のパッケージ名を幻覚しがちかを観察し、その名前をマルウェア入りで公開レジストリに登録します。あなたのアシスタントが trjnhrs-pkg を思いつく。誰かがすでに trjnhrs-pkg を公開している。あなたのインストールコマンドは何事もなく解決する。そして気づけば、他人のコードを実行しているのです。昨日「存在しなかった」importは、今日は意図的に存在し、しかも敵対的です。
これこそ、本当に危険な失敗モードです。タイプミスなら5秒で気づきます。ですが、誰かのペイロードへ静かに解決してしまうそれらしいパッケージ名は、本番に入るまで気づけない類いのものです。
「やめろと言えばいい」が効かない理由
スレッドには、いつものアドバイスが並んでいます。もっと良いプロンプトを書け。間違えるなと指示しろ。警告をエラー扱いにしろ。チェッカーを入れろ。
最初の二つは希望的観測です。確率的なシステムを、持っていない事実について決定論的にすることは、プロンプトではできません。後の二つは惜しいところまで来ていますが、汎用のリンターは症状(解決しないimport)を指摘するだけで、原因を理解しません。依存関係をマニフェストに追加し忘れただけなのか。リンターからは見えない内部モジュールなのか。それとも、このパッケージは地球上のどこにも本当に存在しないのか。この三つのケースは、頭の悪いチェッカーには同じに見えますが、必要な対応はまったく異なります。(自分のコードを自分で見直しても、AIのもっともらしい間違いを拾えないのと同じ理由です。コードを書いたものが、それを検証する唯一の存在であってはいけません。)
そのギャップを埋めるために作ったのが Surmado Code Review です。
どうやって実際に捕まえるのか:決定論的チェックと判断
答えは、より賢いモデルではありません。そもそも、事実に関する問いをモデルに投げないことです。
知る作業は、決定論的チェックが担います。プルリクエストのたびに、Surmado Code Review は差分の中の各importを、事実の裏付けに照らして解決します。あなたのロックファイル、マニフェスト、インストール済みモジュール、標準ライブラリ、社内パッケージです。この工程は推測しません。パッケージは解決するか、しないかのどちらかです。super-fast-parser が差分に現れて、依存グラフにもレジストリにも何も解決しないなら、それは意見ではなく事実です。ここでは生成が一切行われないので、幻覚は起こりようがありません。ただの照合です。
判断する作業は、Scout が担います。事実がそろえば、モデルは本当に得意なこと、つまり仕分けと説明を行います。「package.json への追加を忘れただけ」なのか、「このモジュールは存在せず、いちばん近い実在のものは名前が違う」のかを見分けます。重複を取り除きます。あなたがほぼ間違いなく意図していたimportを指し示します。そして、怖いケースを引き上げます。たとえば、この名前は3日前に公開されたばかりのパッケージに解決し、エコシステム内の他の何もそれを参照していない、というように。それがスロップスクワッティングの匂いであり、単純なリンターにはできない判断です。
どちらの半分も、単独では機能しません。判断のない決定論的チェックはノイズが多く、自分を説明できません。決定論的な裏付けのないモデルは、importを幻覚するもう一つの存在にすぎず、今度はあなたの幻覚importをレビューすることになります。両方を組み合わせると、あのスレッドの全員が本当に欲しかったものが手に入ります。何が本物かという確実性と、どうすべきかという判断です。
どこで動くのか
Surmado Code Review は、あなたのプルリクエストにコメントします。差分をチームの STANDARDS.MD に照らして確認し、でっち上げのimportがマージされる前に印を付けます。同僚のブランチを静かに壊したり、誰も精査していないパッケージを引き込んだりした後ではありません。PRごとに1つのコメント、あなたのルールに紐づき、修正をプッシュすれば同じ場所が書き換わります。「AIが書いた」と「mainに入った」のあいだの層です。
無料で試す
私たちがこれを作ったのは、存在しないimportの問題が自分たちの時間を奪っていたからであり、そのサプライチェーン版が本気で怖かったからです。私たちは自分たちのリポジトリで使っています。どう作ったかはこちら。だから、壁の向こうに隠したりはしません。
Surmado Code Review は月10PRまで無料です。GitHubリポジトリに接続し、STANDARDS.MD を書けば(新しいチームメイトにコードベースを説明するように、会話からScoutが下書きを手伝います)、次のPRから幻覚importを捕まえ始めます。それ以降は月額15ドルで100PRまで。席数による課金はありません。データ保持はゼロです。
あなたのAIは、これからもimportを作り続けます。あなたが、それをマージし続ける必要はありません。
関連記事