
CVE-2026-93349の概念実証。Frictionless <= 5.20.0rc1のexplore CLIにおけるOSコマンドインジェクションで、悪意あるData Package記述子パスを介して発生する。
<= 5.20.0rc1 explore における OS コマンドインジェクション深刻度: 高、CVSS 3.1 8.8
ベクター: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
影響を受けるバージョン: すべての Frictionless バージョン <= 5.20.0rc1
コンポーネント: frictionless.console.commands.explore
CWE: CWE-78 (OS コマンドインジェクション)、CWE-20 (不適切な入力検証)
発見および報告者: Sai Teja Erukude
Frictionless の 5.20.0rc1 プレリリースまでのバージョンには、frictionless explore CLI コマンドに OS コマンドインジェクションの脆弱性が存在します。
このコマンドは、ユーザーが指定した Data Package ディスクリプタを読み込み、リソースパスを収集し、resource.normpath を導出し、それらのパスを単一のコマンド文字列に結合し、その文字列を直接 os.system に渡します:
paths = [resource.normpath for resource in resources if resource.normpath]
os.system(f"vd {' '.join(paths)}")
resources[*].path は datapackage.json からのディスクリプタ制御されたメタデータであるため、攻撃者はリソースパスにシェルのメタ文字を含めることができます。被害者が悪意のあるディスクリプタに対して frictionless explore を実行すると、シェルがこれらのメタ文字を解釈し、注入されたコマンドを実行します。
攻撃者は、frictionless explore を実行しているユーザーのセキュリティコンテキストで任意のコマンドを実行できる可能性があります。
これは、信頼できないプロジェクト、アーカイブ、リポジトリ、または共有データセットから Data Package ディスクリプタを検査、検証、または探索するワークフローに影響を与える可能性があります。
ローカル環境によっては、以下が可能になる場合があります:
脆弱なパスは explore コマンドです:
frictionless explore <package>
-> Package.from_descriptor(...)
-> Resource.list()
-> resource.normpath
-> os.system(f"vd {' '.join(paths)}")
PoC は、resources[0].path に無害なマーカーファイル書き込みペイロードを含む Data Package ディスクリプタを生成します。
Windows では、生成されるパスは & コマンド区切り文字を使用します:
data.csv & echo frictionless_explore_command_injection_triggered>"...\marker.txt" & rem
POSIX システムでは、生成されるパスはセミコロンのコマンド区切り文字を使用します:
data.csv; printf %s frictionless_explore_command_injection_triggered > .../marker.txt; #
ランナーは、インストールされたパッケージから実際の frictionless explore コマンドを呼び出します。意図された vd ビューアが対話的に起動しないように、子プロセスの PATH をクリアしますが、シェルが構築されたコマンド文字列を解析する際に、注入されたコマンドは依然として実行されます。
package_builder.py は、攻撃者が制御する Data Package ディスクリプタと無害な CSV ファイルを作成します。
run_poc.py はディスクリプタを検証し、frictionless explore を呼び出し、実行の証拠を出力します。
ローカルのテスト環境でのみ実行してください:
python -m venv .venv
.venv\Scripts\activate
python -m pip install -r requirements.txt
python -B run_poc.py
含まれている requirements.txt は、この範囲で最新の確認された脆弱なプレリリースである frictionless==5.20.0rc1 を固定しています。
脆弱なバージョンで期待される証拠:
frictionless_version : 5.20.0rc1
installed_package : True
descriptor_valid : True
listed_resource_count : 1
raw_path_contains_payload : True
normpath_contains_payload : True
explore_returncode : 0
viewer_launch_disabled : True
marker_exists : True
marker_contents
frictionless_explore_command_injection_triggered
success : True
重要な証拠は、悪意のあるディスクリプタが有効であり、ディスクリプタ制御されたパスが resource.normpath にまで残り、frictionless explore の実行後に marker.txt が作成されることです。
ペイロードは意図的に無害です。以下のローカルマーカー文字列を書き込むだけです:
frictionless_explore_command_injection_triggered
シェルセッションを生成したり、ネットワークサービスに接続したり、シークレットを読み取ったり、データを削除したり、PoC ディレクトリ外のファイルを変更したりすることはありません。
ディスクリプタ制御されたパスをシェルに渡すことを避けてください。
シェルベースの呼び出しを、引数ベクトルを使用する subprocess.run に置き換えてください:
subprocess.run(["vd", *paths], check=False)
これにより、各リソースパスがリテラル引数として vd に渡されます。パス内のシェルメタ文字は、その単一の argv エントリ内では通常の文字のままであり、実行されません。
特定のパス文字をブラックリストに登録する方法は、シェル構文がプラットフォームやシェルによって異なるため、より弱い対策です。コマンド呼び出しの境界が根本原因であるため、耐久性のある修正はシェル解釈を避けるべきです。
推奨されるパッチについては fix.md を参照してください。
Sai Teja Erukude によって発見および報告されました。
開示は VulnCheck を通じて調整されました。
exploit_walkthrough.mdfix.md