x/sys/execabs: deprecate, isolate, tag, delete
要約
概要
golang.org/x/sys/execabs パッケージを廃止します。このパッケージは、Go 1.19 以降の標準ライブラリ os/exec がデフォルトで同じ安全な動作をするようになったため、役目を終えています。手順は、//go:fix ディレクティブで利用者を os/exec へ自動移行させ、非推奨(Deprecated)にしたうえで、最終的に「isolate(独立モジュール化)、tag(タグ付け)、delete(削除)」する流れです。
ステータス変更
(新規) → likely_accept
このproposalは2023年11月に提出されました。当初は「利用者がまだ多いので、すぐに削除するのは早い」(@bcmills)、「//go:fix によるインライン化(#32816)が使えるようになるまで待つのが妥当」(@rolandshoemaker)という意見が出て、保留になっていました。その後 //go:fix inline が実用段階に入り、利用者の移行を機械的に済ませられるようになりました。これを受けて2026年9月に @aclements が段階的な削除計画を示し、proposal review group が likely accept と判断しました。
技術的背景
現状の問題点
2021年、Windows などで exec.Command("git") がカレントディレクトリ内の git.exe を実行してしまうセキュリティ問題(PATH lookup問題)が見つかりました。対策として、標準ライブラリ内部には internal/execabs、外部パッケージ向けには x/sys/execabs が導入されました。
Go 1.19 では os/exec 自体の動作が変わり、PATH 検索の結果が相対パス(カレントディレクトリ)になった場合は exec.ErrDot を返して実行を拒否するようになりました。そのため internal/execabs は削除済みです。一方、x/sys/execabs は os/exec の薄いラッパーとして残り続けています。しかも内部では reflect と unsafe を使って exec.Cmd の非公開フィールド lookPathErr を書き換えるなど、保守上好ましくない実装を含んでいます。
提案された解決策
x/sys/execabsのCommand、CommandContext、LookPath、各型エイリアス(Cmd、Error、ExitError、ErrNotFound)に//go:fixディレクティブを付け、os/execの同名APIへ転送する- パッケージを Deprecated としてマークする
- x リポジトリの月次タグ付けを待ち、さらに1か月様子を見て問題がないことを確認する
- isolate、tag、delete を行う。具体的には、パッケージを独立させてタグを打ち、既存の利用者が引き続き取得できる状態にしたうえで、x/sys の本体から削除します。
これによって何ができるようになるか
- 利用者は
go fixを実行するだけで、execabsの呼び出しをos/execに機械的に書き換えられます。 - 依存関係から不要な
x/sys/execabsが消え、unsafeを使うコードへの依存もなくなります。 - Go チームは、役目を終えたパッケージの保守から解放されます。
- 新しく書くコードでは、
os/execだけで PATH lookup 問題に対処できることがはっきりします。
コード例
// Before: x/sys/execabs を使う書き方
import "golang.org/x/sys/execabs"
cmd := execabs.Command("git", "status")
out, err := cmd.Output()
// After: go fix により os/exec へ置き換え(Go 1.19 以降は同等の安全性)
import "os/exec"
cmd := exec.Command("git", "status")
out, err := cmd.Output()
if errors.Is(err, exec.ErrDot) {
// カレントディレクトリの実行ファイルに解決された場合はここに来る
}
LookPath の動作には細かい違いがあります。execabs.LookPath は相対パスに解決されるとパスを返さず、エラーだけを返します。一方 exec.LookPath は、パスと exec.ErrDot の両方を返します。
議論のハイライト
- 削除時期: @seankhliao が「非推奨化だけにするか、tag/isolate/delete まで進めるか」を尋ねました。@bcmills は「過去に tag-and-delete したパッケージは何年も使われていなかったものばかりだが、execabs はまだ利用が多い」として、即時削除に慎重な立場を取りました。
//go:fixを待つ判断: @bcmills は、非推奨の警告に対応する利用者の手間を減らすため、//go:fixインライン化(#32816)の完成を待つよう提案しました。@rolandshoemaker も「急ぐ理由はない」と賛成しました。execabs は薄いラッパーなので、残しておくコストは低いと判断されました。- 段階的な削除計画: 約3年の保留を経て、@aclements が「
//go:fixと非推奨化を先に入れ、月次タグ付けを待ち、さらに1か月置いてから削除する」という慎重な手順を示し、これがそのまま提案内容になりました。 - 既存利用者への配慮: 削除の前にタグを打つので、古いバージョンを固定している利用者のビルドは壊れません。