
CVE-2025-68664の詳細な開示。LangChainコアの重大な逆シリアル化脆弱性で、細工されたプロンプトとシリアル化フローを介した秘密情報の外部送信と潜在的なRCEを可能にする。
著者: ヤルデン・ポラット
Cyataリサーチ: LangChainにおけるLangGrinch脆弱性
公開: https://cyata.ai/blog/langgrinch-langchain-core-cve-2025-68664/

昨日、LangChainは、私がlangchain-coreで発見した脆弱性に関する重大なセキュリティアドバイザリを公開しました: CVE-2025-68664 / GHSA-c67j-w6g6-q2cm。
今年の初め、私の研究は、私たちの研究「Vault Fault」においてシークレットマネージャーをハッキングすることに焦点を当てていました。これは、最も機微な認証情報の周囲にセキュリティ境界として特別に設計されたシステムです。何度も繰り返された結論はひとつでした: プラットフォームが攻撃者によって形成されたデータを信頼された構造として誤って処理するとき、その境界は急速に崩壊します。今回「壊れる」システムは、あなたのシークレットマネージャーではありません。それらを使用できるエージェントフレームワークです。
なぜこの脆弱性が特別な注意に値するのか:
それはコアにあります。 これは特定のツールのバグでも、統合のエッジケースでも、「コミュニティのパッケージが何か奇妙なことをした」というものでもありません。脆弱なAPI(dumps() / dumpd())はlangchain-core自体にあります。
影響範囲は巨大です。 ダウンロード数の観点では、langchainは現在世界で最も広く展開されているAIフレームワークコンポーネントのひとつです。2025年12月末時点で、公開パッケージテレメトリは数億回のインストールを示しており、pepy.techは総ダウンロード数約8億4700万を報告し、pypistatsは直近1ヶ月で約9800万ダウンロードを示しています。
ひとつのプロンプトが多くの仕組みを起動できます。 ここでの最も一般的な現実世界の経路は、「攻撃者がシリアライズされたブロブを送信し、あなたがload()を呼び出す」というものではありません。もっと微妙です: LLMの出力はadditional_kwargsやresponse_metadataのようなフィールドに影響を与えることができ、これらのフィールドはシリアライズされ、後にストリーミングログ/イベントのような通常のフレームワーク機能を通じてデシリアライズされる可能性があります。簡単に言えば、これはエクスプロイトが単一のテキストプロンプトによって起動され、予想外に複雑な内部パイプラインへとカスケードする可能性があることを意味します。
読み進める前に、パッチはバージョン1.2.5および0.3.81ですでにリリースされています。LangChainを本番環境で使用している場合、これは見た目よりも複雑です。できるだけ早くアップデートしてください。
LangChainは、'lc'マーカーを含む辞書がLangChainオブジェクトを表す特別な内部シリアライゼーションフォーマットを使用します。脆弱性は、dumps()とdumpd()が、予約されたキー'lc'を誤って含むユーザー制御の辞書を適切にエスケープしていなかったことにありました。
したがって、攻撃者がLangChainのオーケストレーションループに'lc'キーを含むコンテンツをシリアライズさせ、後にデシリアライズさせることができれば、安全でない任意のオブジェクトをインスタンス化でき、攻撃者に有利な多くの経路を潜在的に起動できます。
アドバイザリは、標準的なイベントストリーミング、ロギング、メッセージ履歴/メモリ、キャッシュなど、実際のユースケースで非常に一般的な12の異なる脆弱なフローを列挙しています:

最も壊滅的な影響には以下が含まれます:
環境変数からのシークレット抽出。アドバイザリは、これがsecrets_from_env=Trueでのデシリアライズ時に発生することに言及しています。特筆すべきは、これは昨日まではデフォルトだったことです。🙂
オブジェクトのインスタンス化(事前承認された名前空間内: langchain_core、langchain_openai、langchain_aws、langchain_anthropic… を含む)。コンストラクタ内で副作用(ネットワーク呼び出し、ファイル操作など)を潜在的に引き起こします。
特定の条件下では、LangChainオブジェクトのインスタンス化が任意のコード実行につながる可能性があります。
これはCWE-502: 信頼されていないデータのデシリアライゼーションに分類され、CNA CVSSスコアは**9.3(クリティカル)**です。
クリスマスイブに、私は最も祝祭的でない作業をしていました: シリアライゼーションコードを見つめながら、「待って…なぜこれが信頼されていると見なされるのか?」と自問していました。
セキュリティ研究は外から見ると劇的に見えることがよくあります。実際には、それは通常、注意深いコード読み、小さな仮説、「これはおかしい」という瞬間のゆっくりとした蓄積です。
これはCyataでの多くの研究と同じように始まりました: AIスタックを実際のリスクについて評価するときに私たちが常に問う単純な質問からです:
AIアプリケーションにおける信頼境界はどこにあるのか、そして開発者は本当にその境界がどこにあるのかを知っているのか?
LangChainは強力なフレームワークであり、ほとんどの最新フレームワークと同様に、複雑な構造化データ(メッセージ、ツール呼び出し、ストリーミングイベント、トレース、キャッシュ、「ランナブル」)を移動させる必要があります。
以前の研究を調べると、LangChainツールと統合に関する広範な研究はすでにありましたが、コアライブラリでの発見はほとんどありませんでした。
私は調査を逆方向から始めました。興味深い場所(シンク)を見つけ、次に攻撃者がどのようにしてそこに到達できるかを解明する。デシリアライゼーションは明らかなターゲットでした。
何か意味のあるものを見つけるのにかなりの時間がかかりました。しかししばらくして、攻撃者が制御するデシリアライゼーションプリミティブを仮定すると、環境変数の窃取に使用できるブラインドSSRFを起動できることを発見しました(詳細は近日公開予定)。結果がシークレットの窃取に限定されており、私の主な目標であるRCEではなかったため、私はデシリアライゼーションの監査を続け、時間をかけました。
バグは悪いコードの断片ではなく、コードの欠如でした。dumps()は単に'lc'キーを含むユーザー制御の辞書をエスケープしていませんでした。欠落していたのはデシリアライゼーションではなく、シリアライゼーションパスでのエスケープでした。

何かが間違っていることに気づくのは、何かが欠けていることに気づくよりもはるかに簡単です。特に、最も注意深く監査されたAIフレームワークのひとつで、dumps()ではなくload()を監査している場合はなおさらです。2年半もの間。
そこから、調査は構造化された演習になりました:
信頼されていないコンテンツ(主に任意の辞書)がどこでシリアライゼーションに入るかを特定する(LLM出力、プロンプトインジェクション、ユーザー入力、外部ツール、取得されたドキュメント)。
これらのシリアライズされたデータがいつデシリアライズされるかを特定する。
攻撃者が任意のオブジェクトのインスタンス化から何を達成できるかを特定する。
その時点で、主な発見は責任ある報告に十分明確で実用的でした: dumps() / dumpd()における'lc'キーを持つ辞書の周りのエスケープにギャップがありました。
アドバイザリは後に、私たちが実際に頻繁に見るものを捉えました: additional_kwargsやresponse_metadataのようなフィールドはLLM出力とプロンプトインジェクションによって影響を受ける可能性があり、これらのフィールドは多くのフローでシリアライズ-デシリアライズされる可能性があります。
LangChainチームの功績として、その対応とフォローアップは断固としたものでした。単にバグにパッチを当てるだけでなく、現在の世界に対して許容的すぎたデフォルトを強化しました。
LangChainプロジェクトは、この発見に対して$4,000 USDの報奨金を授与することを決定しました。LangChainが報奨金プログラムを開催していたプラットフォームであるhuntrによると、これはプロジェクトでこれまでに授与された最高額であり、これまでの報奨金は最高$125でした。
LangChainは構造化された辞書フォーマットを使用して特定のオブジェクトをシリアライズします。'lc'キーは「これはLangChainのシリアライズされた構造である」ことを示すために内部的に使用され、単なる任意のユーザーデータではありません。
これは一般的なパターンですが、セキュリティの不変条件を生み出します: 'lc'を含む可能性のあるユーザーデータは注意深く処理されなければなりません。そうでなければ、攻撃者は内部オブジェクト「のように見える」辞書を作成し、デシリアライザーを欺いて値を与えることができます。
パッチは更新されたドキュメントで意図を明確にしています: シリアライゼーション中、'lc'キーを含むプレーンな辞書はラップすることによってエスケープされます。
これにより、デシリアライゼーション中にこれらの辞書が実際のシリアライズされたLangChainオブジェクトと混同されるのを防ぎます。
LangChainのload()/loads()関数は任意のクラスをインスタンス化しません。デシリアライズできるクラスを制御するホワイトリストに対してチェックします。デフォルトでは、このホワイトリストにはlangchain_core、langchain_openai、langchain_aws、およびその他のエコシステムパッケージのクラスが含まれます。
ここに落とし穴があります: ホワイトリスト内のほとんどのクラスは無害なコンストラクタを持っています。悪用可能な経路を見つけるには、エコシステムを掘り下げて、インスタンス化時に何か意味のあることをするクラスを探す必要がありました。私が見つけたものは以下に詳述されていますが、他にも発見されるのを待っているものがあるかもしれません。
LangChainのloads()関数は_secret_タイプをサポートしており、デシリアライゼーション中に環境変数から値を解決できます。パッチ適用前は、この_secrets_from_env_関数はデフォルトで有効でした:
if (
value.get("lc") == 1
and value.get("type") == "secret"
and value.get("id") is not None
):
[key] = value["id"]
if key in self.secrets_map:
return self.secrets_map[key]
if self.secrets_from_env and key in os.environ and os.environ[key]:
return os.environ[key] # <-- Возвращение переменной окружения
return None
デシリアライズされたオブジェクトが攻撃者に返される場合、例えばLLMコンテキスト内のメッセージ履歴などでは、環境変数が漏洩する可能性があります。
しかし、より興味深い経路は間接的なプロンプトインジェクションです。LLMの応答を一切見ることができない攻撃者でも、正しいクラスをインスタンス化することでシークレットを窃取できます。_langchain_aws_の_ChatBedrockConverse_は、_loads_のデフォルトホワイトリストに含まれるだけでなく、構築時にGETリクエストを行います。GETエンドポイントは攻撃者が制御し、特定のHTTPヘッダーは_secrets_from_env_関数を介して環境変数で満たすことができます。

このバリデータは_ChatBedrockConverse_がインスタンス化されるときに実行されます。攻撃者は_endpoint_url_を制御し、送信リクエストを起動します。_secrets_from_env_と組み合わせることで、_aws_access_key_id_ヘッダーはAWSキーだけでなく、任意の環境変数で満たすことができます。
私たちは、セキュリティチームに時間を与えるために、ここで完全なエクスプロイトを意図的に公開していません。数ヶ月後、Huntrサイトが自動的に公開する予定です。
_loads()_のデフォルトホワイトリストにあるクラスの中には_PromptTemplate_があります。このクラスはテンプレートからプロンプトを作成し、利用可能なテンプレート形式のひとつがJinja2です。
テンプレートがJinja2でレンダリングされると、任意のPythonコードが実行される可能性があります。これを_loads()_関数から単独で直接起動する方法は見つかりませんでしたが、デシリアライズされたオブジェクトへの後続の呼び出しがレンダリングを起動する場合、コード実行が続きます。
_loads()_から直接コード実行への経路がある可能性があると疑っていますが、まだ確認していません。テストに値する確かなアイデアや手がかりがあれば、ぜひお聞かせください。これはまさに、セキュリティコミュニティが仮説を証拠に変えるのを支援する場です。🤝
また注目すべき点: 過去のバージョンでは、Chainクラスもホワイトリストに含まれていました。このクラスには、テンプレートレンダリングへのフローを可能にする可能性のある特別な機能がありました。
あなたのアプリケーションは、脆弱なバージョンのlangchain-coreを使用している場合、潜在的に影響を受けます。以下は最も一般的な脆弱なパターンの一部です(合計12のフローが特定されています):
とはいえ、システムの動作は十分に複雑であるため、簡単なコードレビューですべての到達可能なバリアントを明らかにできると想定することはリスクがあります。パッチ適用済みバージョンにアップデートすることが最も安全であり、それを行うまで安全だと想定しないでください。
また、アドバイザリは、私が最も重要な現実世界のポイントだと考えるものを指摘しています:
最も一般的な攻撃ベクトルは、additional_kwargsやresponse_metadataのようなLLM応答フィールドを介して発生します。これらはプロンプトインジェクションを介して制御され、その後ストリーミング操作でシリアライズ/デシリアライズされる可能性があります。
これはまさに「AIが古典的セキュリティに出会う」という交差点であり、組織が不意を突かれる場所です。LLMの出力は信頼されていない入力です。フレームワークがその出力の一部を後で構造化オブジェクトとして処理する場合、攻撃者がそれらを形成しようとすると想定すべきです。
langchain-coreをパッチ適用済みバージョンにアップデートしてください。langchain、langchain-community、または他のエコシステムパッケージを使用している場合は、本番環境に実際にインストールされているlangchain-coreのバージョンを確認してください。
additional_kwargs、response_metadata、ツール出力、取得されたドキュメント、メッセージ履歴を、反証がない限り信頼されていないものとして扱ってください。ログ/イベントをストリーミングし、後でローダーで再水和する場合、これは特に重要です。
アップデート後も、次の原則を守ってください: シリアライズされた入力を信頼しない限り、環境変数からのシークレット解決を有効にしない。プロジェクトは理由があってデフォルトを変更しました。
私のレポートに基づき、LangChainJSには密接に関連するアドバイザリ(GHSA-r399-636x-v7f6 / CVE-2025-68665)があり、同様のメカニズムがあります: シリアライゼーション中の'lc'マーカーの混同により、特定の構成でシークレットの抽出と安全でないインスタンス化が可能になります。
あなたの組織がPythonとJavaScriptの両方のLangChainスタックを実行している場合、これはパターンがエコシステム間で広がることを思い出させるものとして捉えてください: マーカーシリアライゼーション、信頼されていないモデル出力、その後のデシリアライゼーションは、繰り返し発生するリスクの形態です。
私たちは、エージェントAIフレームワークがプロダクションシステム内のクリティカルインフラストラクチャになるフェーズに入っています。シリアライゼーションフォーマット、オーケストレーションパイプライン、ツール実行、キャッシュ、トレースはもはや「配管」ではありません。それらはあなたのセキュリティ境界の一部です。
この脆弱性は「単なるライブラリのバグ」ではありません。これは大きなパターンのケーススタディです:
Cyataでは、私たちの仕事は、組織がAIシステムの周りに可視性、リスク評価、制御、ガバナンスを構築するのを支援することです。なぜなら、_エージェントがどこで実行されているか、どのバージョンが展開されているか、どのデータが流れているか_に迅速に答えることができなければ、このようなアドバイザリが届いたときに、効果的に盲目的に飛んでいることになるからです。
これを読んでいるセキュリティリーダーであれば、ここに心地よくない真実があります:
ほとんどの組織は現在、迅速かつ自信を持って答えることができません:
これは「開発者の問題」ではありません。これは可視性とガバナンスの問題です。
そして、ここでCyataの登場です。
Cyataでは、実際的な成果に焦点を当てています: 開発者を遅らせることなくAIとエージェントのリスクを軽減すること。このような脆弱性は「単なるパッチ」であることはまれです。それらは、チームがエージェントがどこで実行されているかを発見し、実際の信頼境界を理解し、急速に動くフレームワークでより安全なデフォルトを確保する方法におけるギャップを明らかにします。
何がどこで実行され、どのように接続されているかを把握します。
CVEの最初の質問に迅速に答えます: 私たちは影響を受けていますか?どのフローで?
エージェントのランタイムと環境間の統合(IDE、CI、サービス、ジョブ、ホスティングされたエージェント)を発見します。
使用中のフレームワーク、パッケージ、バージョンを追跡します。
「ライブラリが存在する」というだけでなく、実際の影響範囲に基づいて重要なものを優先順位付けします。
より迅速なトリアージを可能にします: 何がインターネットに面しているか、何がシークレットに触れるか、何が昇格した特権で実行されるか。
最高リスクの経路を特定します: 特権コンテキスト(シークレットを持つサービス、広範なツール権限、本番ネットワークアクセス)に流れ込む信頼されていないコンテンツ。
「構造化フィールド」が信頼境界を横断する可能性がある場所を強調します(メタデータ、ツール出力、ストリーミングイベント、キャッシュされたアーティファクト)。
すべての依存関係がどこでもパッチ適用される前に、露出を軽減します。
より安全な運用デフォルトを奨励します: 最小特権、分離境界、チーム間でスケールするポリシーチェック。
リスクのあるパターンの周りにゲートウェイを確保します(例: 信頼されていないデータのデシリアライゼーション、寛容なオブジェクトの再生成、安全でないストリーミング-キャッシュ-再水和フロー)。
信頼されていないコンテキストで機微な機能をゲートまたは制限します(例: 環境からのシークレットアクセス、高特権のツール実行、または特権ワーカーでのリスクのあるコードパスの起動)。
「エージェントの安全な使用」を反復可能で、監査可能で、ドリフトしにくいものにします。
クリスマスのアドバイザリが届いたとき、目標はヒロイズムではなく、実際のインベントリと確保されたゲートウェイに支えられた、穏やかで制御された対応です。
Huntrを通じてレポートを送信 – 2025年12月4日
LangChainメンテナーによって確認 – 2025年12月5日
アドバイザリとCVEが公開 – 2025年12月24日