メインコンテンツへスキップ

Go Proposal Weekly Digest

Go言語のproposal更新を毎週お届け

#80415likely_accept

syscall: update Windows SysProcAttr for recent process creation features

ステータス変更: active likely_accept

要約

AIによる要約であり、誤りを含む場合があります。

概要

Windows版syscall.SysProcAttrにジョブオブジェクト・コンソール・デスクトップ・AppContainer・実験的サンドボックスといった、Windowsプロセス生成の高度な機能を制御するための新フィールドを追加する提案です。os/exec経由でこれらのWin32機能を安全に利用できるようにすることを目的としています。

ステータス変更

activelikely_accept
提案レビュー会議(@aclements)は、議論で提起された懸念(特にJobsフィールドのnilと空スライスの扱い、および実験的なSandbox APIを標準ライブラリに組み込むことの是非)がいずれも解消されたと判断し、2026年9月9日に likely_accept としました。特にJobsについては、Win32 APIの実地検証(UpdateProcThreadAttributeの挙動確認)により、空のジョブリストに意味のある状態は存在しないことが確認され、nilと空スライスを同一視する(len(Jobs) > 0の場合のみ属性を設定する)という結論に至りました。

技術的背景

現状の問題点

package syscallは基本的に凍結されており、新しいフィールドの追加は最小限に留められています。しかし、Windowsのジョブオブジェクトによるサンドボックス化、専用コンソール/デスクトップでのプロセス起動、AppContainerによる分離、Microsoftが新たに公開した実験的サンドボックスAPI(Experimental_CreateProcessInSandbox)などを利用するには、現状os/execossyscallのプロセス生成ロジックをまるごとフォークして書き換える必要があり、非常に手間がかかります。

提案された解決策

Windows版syscall.SysProcAttrに以下のフィールドを追加します。

Jobs         []Handle       // 非空なら、このジョブオブジェクトリストでプロセスを開始
Console      Handle         // 非ゼロなら、このコンソールに接続してプロセスを開始
Desktop      string         // 非空なら、指定したデスクトップでプロセスを開始
AppContainer *AppContainer  // 非nilなら、このメタデータでAppContainerプロセスを作成
Sandbox      *Sandbox       // 非nilなら、記述されたサンドボックスでプロセスを開始

新しい型AppContainer(WindowsのSECURITY_CAPABILITIES構造体の型安全なGo版)とSandbox(FlatBuffersエンコードされた仕様を保持する[]byteフィールドを持つ、将来のスキーマ変更を吸収できる設計)も追加されます。Sandboxのスペック自体のパース・構築ロジックはsyscallには含めず、必要に応じてgolang.org/x/sys/windows側で追従する方針です。

これによって何ができるようになるか

os/execを使ったまま、Windowsのプロセス隔離・制御機能に直接アクセスできるようになります。

  • ビルドサンドボックス: Bazel/Buildbarnのようなリモート実行系が、ジョブオブジェクトでリソース制限や親子プロセス管理を行うプロセスをos/execだけで起動できる。
  • エージェント/ツールのサンドボックス化: AppContainerや実験的サンドボックスAPIを用いて、権限を制限した状態で外部コマンドやAIエージェントのツール実行を隔離できる。
  • GUIアプリのコンソール/デスクトップ制御: 特定のコンソールやデスクトップにアタッチしたプロセスを起動でき、ターミナルエミュレータや自動化ツールでの制御性が向上する。

コード例

// Before: syscallをフォークしてCreateProcess呼び出しを自前実装する必要がある
// (os/exec, os, syscall の内部ロジックをコピー・改変)
// After: SysProcAttrに新フィールドを指定するだけ
cmd := exec.Command("worker.exe")
cmd.SysProcAttr = &syscall.SysProcAttr{
    Jobs: []syscall.Handle{jobHandle}, // 非空の場合のみジョブリスト属性を付与
}
err := cmd.Start()

議論のハイライト

  • Sandboxフィールドは、Microsoftが2026年5月に公開したばかりの実験的API(Experimental_CreateProcessInSandbox)に依存しており、@magicalから「まだリリースされていない実験的機能に標準ライブラリで先行対応するのは時期尚早ではないか」という強い異議が出された。
  • @rscは、最悪のケースでも「使われなくなった1フィールドが残るだけ」でリスクは小さいこと、MicrosoftはAPIシグネチャレベルの破壊的変更をしない可能性が高いこと、[]byteによるFlatBuffersスキーマの前方互換設計により将来の仕様変更を吸収できることを説明し、反論した。@qmuntal@alexbrainmanもこれを支持し、最終的にSandboxフィールドも維持された。
  • @neildの要求を受けてAPI仕様が明文化され、コミュニティレビューが進んだ。
  • 実装検証を行った@alex-the-thirdにより、Jobsフィールドで非nilの空スライスを渡すとERROR_BAD_LENGTHで失敗するというエッジケースが発見された。これを受けて@aclementsらが議論した結果、Win32 APIの実地検証で「空のジョブリストに意味のある状態はない」と判断され、nilと空スライスを同一視する仕様に修正された。
  • 実装はCL 801640として進行中だが、テストとSandbox部分の実装がまだ不足していることが@alexbrainmanから指摘されている。

関連リンク