SSD Nodes Learn 🎉 VPS $5.50/月〜
ガイド Matt Connor著者 Matt Connor ・更新日 2026-08-13

Ubuntu 26.04のsudo-rsでsudoersはどう変わる?

Ubuntu 26.04ではsudo-rsが標準のsudoになります。sudoersの引数内ワイルドカードは照合されなくなるため、影響する記述と置き換え方を確認できます。

Ubuntu で sudo-rs が変更する点

Ubuntu 26.04 LTS では sudo-rs がデフォルトの sudo としてリリースされるため、新規サーバーで sudo コマンドを実行すると、従来の C プログラムではなく Rust による再実装が起動します。ほとんどの sudoers ファイルは、これまでどおり動作します。問題になるのは、コマンドの引数内にワイルドカードを含むルールです。sudo-rs は引数の文字列に対して glob パターンを照合しないためです。

Ubuntu 25.10 で先に切り替えが行われ、Ubuntu 26.04 LTS でもこの構成が維持されました。Ubuntu 24.04 LTS は、手動で sudo-rs をインストールしない限り従来の sudo を選択するため、影響を受けません。この変更が問題になるのは、Ubuntu 24.04 から 26.04 にアップグレードするとき、または新しいリリースで新規サーバーを構築するときです。中間リリースも運用している場合は、サーバー上での LTS と中間 Ubuntu リリースの違いで、このような変更がどのマシンに最初に適用されるかを確認できます。

実際にサーバーで実行されている sudo を確認する

リリース番号から推測しないでください。マシン自体に確認します。

sudo --version
update-alternatives --config sudo
dpkg -l 'sudo*'

インターネット上のバージョン一覧やこのページの情報よりも、自分のサーバー上の sudo --version を信頼してください。update-alternatives --config sudo はもう一方の確認手段です。インストールされている /usr/bin/sudo のプロバイダーをすべて一覧表示し、選択されているものに印を付けます。パッケージがインストールされていることと、選択されていることは同じではありません。そのため、パッケージ一覧ではなく選択状態を確認してください。

移行期間中は、両方の実装がパッケージとして提供されます。Rust 版は sudo-rs で、2026年8月時点では 26.04 でバージョン 0.2.13 です。Todd C. Miller が開発・保守してきた従来版は sudo.ws としてパッケージ化されており、そのプログラム名には .ws サフィックスが付きます。該当するプログラムは sudo.wsvisudo.ws です。

Ubuntu が sudo-rs に切り替えた理由

sudo は setuid root です。システム上のすべてのユーザーが起動でき、完全な権限で実行を開始するため、内部のメモリバグはローカル root 権限昇格につながります。CVE-2021-3156 はまさにその例です。すべてのローカルユーザーから到達可能なヒープバッファオーバーフローであり、リリース済みのコードに約 10 年間存在していました。Rust はこの種のバグをコンパイル時に検出します。これが書き換えの主な理由です。

2 つ目の理由は、機能範囲です。そして、こちらが設定に影響します。元の sudo は 30 年にわたって多くの機能を取り込んできました。各機能が、root として実行されるコードを増やします。sudo-rs は意図的に機能の一部だけを実装しています。開発者がニッチ、または有害と判断した機能は実装されませんでした。そのため、何年も動作していた sudoers の構文が、単に存在しない場合があります。ワイルドカード規則もその 1 つです。

メモリ安全性によって、バグの 1 種類は排除できます。しかし、プログラムからすべてのバグがなくなるわけではありません。sudo-rs もデフォルトになってから独自のセキュリティ修正をリリースしています。他のソフトウェアと同様に、パッチを適用してください。

対応する sudoers ルール

ファイル自体は同じです。sudo-rs は /etc/sudoers/etc/sudoers.d/ 内の drop-in ファイルを読み込み、サーバー運用者が通常記述する次の内容に対応しています。

  • deploy ALL=(ALL:ALL) ALL、および %sudo ALL=(ALL:ALL) ALL などのグループ形式
  • NOPASSWD: タグと PASSWD: タグ
  • User_AliasRunas_AliasHost_AliasCmnd_Alias
  • 引数を完全に指定したコマンド。例: /usr/bin/systemctl restart app-api
  • "" を続けたコマンド。引数なしの場合に限り、そのコマンドを許可します
  • 最後の引数として * を続けたコマンド。後続する任意の引数を許可します
  • / で終わるディレクトリパス。そのディレクトリ内の任意のコマンドを許可します
  • !。リストからコマンドを除外します
  • Defaults のうち、secure_pathenv_keepenv_checktimestamp_timeoutpasswd_trieseditorumasktargetpwrootpwuse_pty などの実用的なサブセット

2 つの defaults は動作が異なるため、注意が必要です。env_reset は sudo-rs で無効にできず、常に有効です。use_pty はデフォルトで有効なため、コマンドは専用の pseudo-terminal 内で実行されます。

ワイルドカードを含む sudoers ルールが一致しなくなった理由

ワイルドカードが引き続き使用できる場所は 1 つだけです。それはコマンドのファイル名です。%ops ALL = /sbin/fsck* のルールでは、sudo fscksudo fsck_exfat も引き続き許可されます。* はファイルシステムとの照合対象になるパスの一部だからです。

引数リスト内で sudo-rs が受け付ける特殊な形式は 2 つだけで、どちらもパターンではありません。"" は引数なしを意味します。末尾の * は、後続する任意の引数を意味します。それ以外の引数は、リテラルテキストとして比較されます。そのため、%ops ALL = /sbin/service ntp * は問題ありません。ntp はリテラルであり、* が末尾にあるためです。ただし、次のようなルールでは、意図した権限が何も付与されません。

deploy ALL=(root) NOPASSWD: /usr/bin/systemctl restart app-*

app-* は引数の途中にあるパターンです。sudo-rs はこれを展開しないため、このルールは systemctl restart app-api に適用されず、sudo はコマンドを拒否します。自分のサーバー上のルールについて事実を確認するには、2 つのコマンドを使用します。root として実行する sudo -l -U deploy は、そのアカウントが実際に実行できる内容を表示します。sudo visudo -c は、ファイルを解析できるかどうかを示します。推測で編集を始める前に、これらを実行してください。

ワイルドカード規則は常に抜け穴でした

元の sudo では、入力した引数を 1 つの文字列に連結し、glob を使って規則の引数文字列と照合します。glob は空白にも一致します。ここが、ほとんどの人が見落とす点です。

sudo-rs のドキュメントには、最も分かりやすい例が示されています。/bin/rm *.txtという規則は sudo rm -rf /home .txtも許可します。1 つの *-rf /home を取り込み、連結された文字列が最後に .txtで終わるためです。この規則は「テキストファイルだけ」と読めます。しかし実際には、「行末が .txt である限り、引数は何でもよい」という意味になります。

systemctl の例でも同じです。引数は 1 つの連結された文字列として比較されるため、末尾のパターンはその後に追加された内容にも一致します。したがって、restart app-*restart app-apiに加えて、呼び出し側が追加する任意の引数も許可します。引数内のパターンは、その前後にある引数まで無制限にします。コマンドの権限は引数によって決まります。sudo-rs は、この構文を安全にする方法を試すのではなく拒否します。安全な一般形が存在しないためです。

ワイルドカードを明示的なコマンドリストに置き換える

多くのワイルドカードルールは、4 行を入力したくなかったために存在します。4 行を入力してください。

Cmnd_Alias APP_RESTART = /usr/bin/systemctl restart app-api, /usr/bin/systemctl restart app-worker
Cmnd_Alias APP_STATUS = /usr/bin/systemctl status app-api, /usr/bin/systemctl status app-worker
deploy ALL=(root) NOPASSWD: APP_RESTART, APP_STATUS

パスを正しく指定してください。バイナリが /usr/bin/systemctl にあるシステムで /bin/systemctl を指定するルールは一致しません。この失敗は権限の問題と同じように見えます。command -v systemctl で確認し、出力内容を貼り付けてください。

ルールは /etc/sudoers に直接記述せず、専用の drop-in ファイルに記述してください。そうすれば、パッケージのアップグレードによって編集内容が上書きされることはありません。

sudo visudo -f /etc/sudoers.d/90-deploy
sudo visudo -c
sudo -l -U deploy

ファイル名にはドットを含めず、末尾にチルダを付けないでください。元の sudo は、sudoers.d にある名前にドットを含むファイルを無視します。そのため、90-deploy.conf は典型的なサイレントな無操作になります。この規則に従っても手間はかかりません。

許可する対象が多い場合はroot所有のラッパーを使用する

許可する対象を列挙するには多すぎる場合は、判定処理をsudoersから切り離し、rootが所有する小さなプログラムに移します。

sudo tee /usr/local/sbin/app-restart >/dev/null <<'EOF'
#!/bin/sh
set -eu
case "${1:-}" in
  app-api|app-worker) ;;
  *) echo "app-restart: not allowed: ${1:-}" >&2; exit 1 ;;
esac
exec /usr/bin/systemctl restart "$1"
EOF
sudo chown root:root /usr/local/sbin/app-restart
sudo chmod 0755 /usr/local/sbin/app-restart
ls -l /usr/local/sbin/app-restart

sudoers側では、1つのコマンドだけを指定します。

deploy ALL=(root) NOPASSWD: /usr/local/sbin/app-restart *

末尾の*は、この場合は許容できます。許可する内容を決めるのはsudoではなく、スクリプトだからです。ただし、スクリプトをrootが所有し、他のユーザーが書き込めない場合に限ります。deployでファイルに書き込める場合、deployは内容を置き換えて、rootとして任意の処理を実行できます。これは、削除したワイルドカード規則よりも危険です。ls -lでモードを確認してください。出力の意味が明確でない場合は、drwxr-xr-x形式の権限文字列を読む方法を5分で学べます。同じ規則はディレクトリにも適用されます。アカウントが/usr/local/sbinに書き込めてはいけません。書き込み可能なディレクトリでは、ファイル全体を置き換えられるためです。

sudo ルールではなく、ジョブ専用のアカウントを割り当てる

多くの場合、先に考えるべきなのは、そのコマンドに本当に root が必要かどうかです。専用ユーザーで実行するサービスは、そのユーザーで管理できるため、sudoers の設定は必要ありません。system unit では、systemd がこの判断をすでに polkit に委任しています。そのため、1 つの unit と 1 人の実行担当者を指定するルールを設定できます。

polkit.addRule(function(action, subject) {
    if (action.id == "org.freedesktop.systemd1.manage-units" &&
        action.lookup("unit") == "app-api.service" &&
        subject.user == "deploy") {
        return polkit.Result.YES;
    }
});

これを /etc/polkit-1/rules.d/50-app-api.rules として保存すると、deploy は sudo を一切使わずに systemctl restart app-api を実行できます。実際に使用する環境と同じコンテキストからテストしてください。SSH セッションで動作するルールでも、cron から利用する前に確認する必要があります。いずれにしても、処理を実行するアカウントは、その処理専用に用意するべきです。これは VPS で最小権限のユーザーアカウントを使用する という考え方と同じです。

sudo-rs で省略されている機能

sudo -E は実装されていません。必要な変数は、代わりに Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY" で指定してください。また、env_reset は常に有効なため、保持されない変数はすべてクリアされます。

LDAP に保存する sudoers の集中管理は廃止されています。sudoers.ldapcvtsudoers は実装されておらず、sudo-ldap パッケージは 26.04 で削除されました。PAM または SSSD を介した LDAP 認証は引き続き機能します。対象外なのは、ディレクトリにポリシーを保存する機能です。

許可されたコマンドからのシェルエスケープを阻止しようとした INTERCEPT は実装されていません。そもそも、決意したユーザーに対して有効な対策ではありません。ルールによってエディターまたはインタープリターを root として実行できるなら、そのユーザーは root 権限を持っています。sudo のオプションでこれを変えることはできません。

セッション記録は実装されていないため、I/O ログも sudoreplay もありません。ログは syslog にのみ送られます。また、別の場所へリダイレクトする logfile オプションもないため、sudo のメッセージはシステムが通常 syslog を送信している場所に記録されます。

sudo.ws に戻すべきでしょうか?

戻すことはできます。26.04 サイクル中も、まさにこの理由から元のパッケージが提供され続けます。

sudo apt install sudo.ws
update-alternatives --config sudo
sudo update-alternatives --set sudo /usr/bin/sudo.ws

このページではなく、--config の出力からパスを正確にコピーしてください。その一覧が、実際にシステムで受け入れられるパスだからです。後で sudo-rs に戻す場合は、同じ一覧にある sudo-rs のバイナリパスを alternative に設定します。

sudo に影響する操作を行う前に、ログインしたままアイドル状態にしておく SSH セッションをもう1つ開いてください。解析に失敗する sudoers ファイルや、インストールされていないバイナリを指す alternative によって、リモートホストで root になる手段を失うことがあります。この習慣は、新しい VPS の最初の10分間に行う他の作業と同じように重要です。

この切り戻しは修正ではなく、期限付きの暫定対応と考えてください。ルールを正しく書き直すための1週間を確保できます。書き直し自体にも価値があります。削除するワイルドカードルールはすべて、作成者が意図した範囲を超える権限を付与していたからです。

FAQ

Ubuntu 26.04 で sudoers のワイルドカード規則が機能しなくなったのはなぜですか?

Ubuntu 26.04 LTS ではデフォルトの sudo に sudo-rs が選択され、sudo-rs はコマンドの引数内にあるワイルドカードパターンに一致しないためです。コマンドのファイル名にはワイルドカードを使用できます。また、"" は引数なしを意味し、最後の引数として単一の * を使用できます。/usr/bin/systemctl restart app-* のような規則は引数の途中にパターンを置くため、何も許可せず、コマンドは拒否されます。root として sudo -l -U deploy を実行し、そのアカウントに実際に許可されている内容を確認してください。その後、規則を正確なコマンド、または root が所有するラッパースクリプトに置き換えます。

Ubuntu 26.04 で元の sudo に戻すにはどうすればよいですか?

元の sudo は sudo.ws としてパッケージ化されています。sudo apt install sudo.ws でインストールし、sudo update-alternatives --set sudo /usr/bin/sudo.ws で alternative の参照先を切り替えます。最初に update-alternatives --config sudo を実行して、システムで利用できる正確なパスを確認してください。切り替え中は、2 つ目の SSH セッションを開いたままにします。どの実装を選択しても、26.04 で削除された sudo-ldap は復元されません。

sudo-rs は同じ /etc/sudoers ファイルを読み取りますか?

はい。sudo-rs は /etc/sudoers/etc/sudoers.d/ 配下の drop-in ファイルを読み取り、ユーザー、グループ、alias、run-as 指定、NOPASSWD タグについて同じ構文を使用します。ただし、sudoers 言語のサブセットを実装しているため、違いは動作の相違ではなく、利用できない構文として現れます。sudo visudo で編集し、セッションを終了する前に sudo visudo -c で検証してください。

sudo-rs では sudo -E の代わりに何を使用しますか?

sudo -E は実装されていません。元の sudo でも、すでに使用が推奨されていませんでした。呼び出し元が制御する環境を root プロセスに渡すと、そのプロセスの動作を変更できるためです。sudoers では、実際に必要な変数を Defaults env_keep += "HTTP_PROXY HTTPS_PROXY NO_PROXY" のような行で明示してください。sudo-rs では env_reset が常に有効で、無効化できません。そのため、保持しない変数はすべて削除されます。

#sudo#sudo-rs#ubuntu#sudoers#permissions