Podのアノテーションがホストを開ける — Kata Containers CVE-2026-44210 を設定から確かめる

コンテナの脆弱性には、大きく2種類ある。壊れたコードを踏むものと、壊れていないコードが設計どおりに動いた結果、境界が消えるものである。後者はパッチの話をする前に「そもそもこの機能は誰に開いているのか」を確認しないと判断できない。

Kata Containers の CVE-2026-44210 は後者にあたる。バッファオーバーフローもメモリ破壊もない。Pod のアノテーションという正規の入口から、ハイパーバイザ側のプロセスに引数を渡せる。その引数の組み合わせ次第で、ゲストVMからホストのルートファイルシステム全体が見える。

そして厄介なのは、これが特別な設定をした人だけの問題ではないことだ。GitHub のセキュリティアドバイザリ GHSA-rr59-xxvx-96qr は「versions prior to 3.31.0 ship with a default configuration that allows pod creators to inject arbitrary command-line arguments」と書いている。既定でそうなっている。

この記事では、何が起きるのかを引数の意味から読み解き、自分の環境が該当するかを機械的に判定するところまでやる。最後に configuration.toml を読んで判定する依存なしのスクリプトを置く。手元のファイルにそのまま当てられる。

何が起きるのか

Kata Containers は、コンテナを軽量VMの中で動かす。ホストとゲストの間でファイルを共有するのに virtiofsd というデーモンを使い、「ホスト側のこのディレクトリを、ゲストのここに見せる」という対応を作る。

問題は、この virtiofsd に渡すコマンドライン引数を、Pod のアノテーションから追加できることだった。

1
io.katacontainers.config.hypervisor.virtio_fs_extra_args

名前のとおり「追加の引数」である。追加なので、既存の引数を消すことはできない——ように見える。ところが virtiofsd の引数はあとから指定したものが効く形になっており、共有元ディレクトリを指定し直せてしまう。アドバイザリが挙げているのは次の組み合わせである。

  • -o source=/ … 共有するホスト側ディレクトリをルートにする
  • --no-announce-submounts … サブマウントの通知を止める
  • --sandbox=none … virtiofsd 自身のサンドボックス化をやめる

これで「ゲストからホストのルートFSが見える」状態ができる。あとはゲスト側からマウントすればよい。そのゲスト側の足場も、もう1つのアノテーションで作れる。

1
io.katacontainers.config.hypervisor.kernel_params

ゲストカーネルの起動パラメータを足せるので、Kata のエージェントのデバッグコンソールを有効化できる。このアノテーションも既定で許可されていた。結果として、Pod を作れる権限さえあれば、VM に入り、ホストの /etc/shadow を含む任意のファイルを読み書きできる。

CVSS 3.1 は 9.9(Critical)、ベクタは AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H。ここで見るべきは2つある。

S:C(Scope Changed) — 影響がコンテナの境界を越えてホストに及ぶ、という評価である。Kata を使う動機がまさに「境界を強くすること」なので、この S:C は機能の目的そのものを打ち消している。

PR:L(低い権限が必要) — 攻撃者は Pod を作れる必要がある。裏を返すと、Pod を誰に作らせているかでリスクがそのまま決まる。

なお同じ CVE に付いている CVSS 4.0 の評価は 5.8(Medium)で、3.1 の 9.9 とかなり開きがある。片方だけを見て判断しないほうがよい。

「うちは大丈夫」が成り立たない理由

この手の話でいちばん多い判断ミスは、「特殊なアノテーションなんて使っていないから関係ない」である。これは2つの点で成り立たない。

第一に、使っているかどうかではなく、使えるかどうかが問題である。許可リストに載っていれば、Pod を作れる誰もが使える。自分が使っていないことは、他人が使えないことを意味しない。

第二に、その許可リストの既定値がこの2つを含んでいた。設定を触っていない環境こそ該当する。

ではリスクの大小は何で決まるか。PR:L の中身、つまり Pod 仕様を誰が組み立てるかである。

  • 自組織の運用者だけが Pod を作る … 攻撃者はまず内部に足場を作る必要がある。緊急度は相対的に下がる。
  • テナントや顧客に Pod 作成を許している … Kata に期待していた分離が、そのまま成立しない。ここが最も危ない。
  • CI やアプリが外部入力から Pod 仕様を組み立てる … 入力の検証次第で、実質的に外部から届く。

3番目は見落とされやすい。マニフェストのテンプレートに、ユーザー由来の値をアノテーションとして流し込んでいないか確認したほうがよい。

自分の環境を判定する

判定の手順は3つ。

  1. Kata のバージョンを実測するkata-runtime --version などランタイム側で見る。3.31.0 以上なら修正済み。
  2. configuration.tomlenable_annotations を見る。ここに何が載っているかが許可リストである。
  3. Pod を作れる主体を棚卸しする。RBAC で podscreate を持っているのは誰か。

2 は目視でもできるが、環境ごとに設定ファイルが分かれていたり、ハイパーバイザ別のセクションが複数あったりするので、機械に読ませたほうが早い。

ここで1つ注意がある。Kata の enable_annotations の各要素は正規表現として解釈される。つまり ".*" と書くと全許可になる。目視だと「1個しか書いていないから安全そう」に見えてしまう典型的な落とし穴で、判定スクリプトはここを見る必要がある。

実際に試す

configuration.toml を読んで、CVE-2026-44210 に関わるアノテーションが許可されているかを報告するスクリプトである。依存なし、Node.js だけで動く。kata-annotation-audit.js として保存する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#!/usr/bin/env node
// kata-annotation-audit.js — Kata Containers の configuration.toml を読み、
// CVE-2026-44210 に関わるアノテーションが許可されているかを報告する。
// 依存なし。node kata-annotation-audit.js <configuration.toml>
"use strict";
const fs = require("fs");

// CVE-2026-44210 で悪用されたアノテーション(GHSA-rr59-xxvx-96qr)
const DANGEROUS = new Map([
["virtio_fs_extra_args", "virtiofsd へ任意の引数を注入できる。-o source=/ でホストのルートFSを共有させられる"],
["kernel_params", "ゲストカーネルの起動パラメータを注入できる。エージェントのデバッグコンソールを有効化できる"],
]);

function parseEnableAnnotations(toml) {
// enable_annotations = ["a", "b"] を(複数行にまたがる形も含めて)拾う。
// TOML の完全なパーサではなく、この1キーだけを見る割り切った実装。
const out = [];
const re = /^\s*enable_annotations\s*=\s*\[([\s\S]*?)\]/gm;
let m;
while ((m = re.exec(toml)) !== null) {
for (const item of m[1].split(",")) {
const s = item.trim().replace(/^["']|["']$/g, "");
if (s) out.push(s);
}
}
return out;
}

function audit(toml) {
const enabled = parseEnableAnnotations(toml);
const findings = [];
for (const name of enabled) {
// 許可リストは正規表現として解釈されるため ".*" のような値は全許可を意味する
if (name === ".*" || name === "*") {
findings.push({ level: "critical", name, why: "すべてのアノテーションを許可している(危険なものも含む)" });
continue;
}
for (const [danger, why] of DANGEROUS) {
if (name === danger || new RegExp(`^${name}$`).test(danger)) {
findings.push({ level: "critical", name, matched: danger, why });
}
}
}
return { enabled, findings };
}

if (require.main === module) {
const path = process.argv[2];
if (!path) {
console.error("usage: node kata-annotation-audit.js <configuration.toml>");
process.exit(2);
}
const { enabled, findings } = audit(fs.readFileSync(path, "utf8"));
console.log(`enable_annotations: ${enabled.length ? enabled.join(", ") : "(未設定)"}`);
if (!enabled.length) {
console.log("判定: enable_annotations が無い。Kata のバージョンによって既定値が違うため、");
console.log(" kata-runtime のバージョンと既定値を必ず併せて確認すること。");
process.exit(0);
}
if (!findings.length) {
console.log("判定: CVE-2026-44210 に関わるアノテーションは許可されていない");
process.exit(0);
}
for (const f of findings) {
console.log(`[${f.level}] ${f.name}${f.matched ? ` -> ${f.matched}` : ""}: ${f.why}`);
}
process.exit(1);
}

module.exports = { audit, parseEnableAnnotations, DANGEROUS };

動かしてみる。まず該当する設定。

1
2
3
4
5
6
7
8
9
10
11
12
$ cat > sample.toml <<'EOF'
[hypervisor.qemu]
path = "/usr/bin/qemu-system-x86_64"
enable_annotations = ["kernel_params", "virtio_fs_extra_args", "initrd"]
EOF

$ node kata-annotation-audit.js sample.toml
enable_annotations: kernel_params, virtio_fs_extra_args, initrd
[critical] kernel_params -> kernel_params: ゲストカーネルの起動パラメータを注入できる。エージェントのデバッグコンソールを有効化できる
[critical] virtio_fs_extra_args -> virtio_fs_extra_args: virtiofsd へ任意の引数を注入できる。-o source=/ でホストのルートFSを共有させられる
$ echo $?
1

危険なものを外した設定。

1
2
3
4
5
6
7
8
9
10
$ cat > safe.toml <<'EOF'
[hypervisor.qemu]
enable_annotations = ["initrd", "image"]
EOF

$ node kata-annotation-audit.js safe.toml
enable_annotations: initrd, image
判定: CVE-2026-44210 に関わるアノテーションは許可されていない
$ echo $?
0

そして、目視だと見落としやすい全許可。

1
2
3
4
5
6
7
8
9
10
$ cat > wild.toml <<'EOF'
[hypervisor.qemu]
enable_annotations = [".*"]
EOF

$ node kata-annotation-audit.js wild.toml
enable_annotations: .*
[critical] .*: すべてのアノテーションを許可している(危険なものも含む)
$ echo $?
1

.* の行は、危険なアノテーション名がどこにも書かれていないのに critical になる。許可リストが正規表現であるというこの1点を知らないと、目視のレビューはここを素通りする。

終了コードを 0 と 1 で分けてあるので、そのまま CI に置ける。

1
$ find /etc/kata-containers -name 'configuration*.toml' -exec node kata-annotation-audit.js {} \;

対処と、更新までの緩和

対処は 3.31.0 以上への更新である。修正コミットは ffa59ce

すぐ更新できない場合、この CVE は緩和が効くほうの部類に入る。理由は、悪用経路が設定で閉じられるからだ。

  1. enable_annotations から virtio_fs_extra_argskernel_params を外す。設定変更だけで完結する。
  2. Pod 仕様の検証(アドミッションコントロール)で、io.katacontainers.config.hypervisor.* のアノテーションを拒否する。1 を回避する経路が他に無いかを気にせずに済む。
  3. Pod の作成権限を棚卸しする。これは緩和というより、PR:L の前提を自分で把握する作業である。

順序としては 1 → 2 → 3 だが、3 は 1 と 2 の緊急度を決める材料なので、実際には最初に手をつけたほうがよいことが多い。

まとめ

  • CVE-2026-44210 は、壊れたコードではなく既定で開いていた入口の問題である。「特殊な設定をしていないから安全」は成り立たない。
  • 危険度は CVSS の 9.9 ではなく、Pod を誰が作れるかPR:L の中身)で決まる。マルチテナントで Kata を分離境界に使っている環境が最も危ない。
  • enable_annotations正規表現の許可リストなので、.* の一行が全許可になる。目視レビューが落としやすいのはここ。
  • 対処は 3.31.0 以上への更新。設定変更だけで効く緩和があるので、更新までの間も手は打てる。

各クラウド(AWS / GCP / Azure)と Linux での対応状況は CVE Watch にまとめている。この記事で扱った CVE-2026-44210 のほか、同時期に公開された Apache Thrift の CVE-2026-55971(C++ バインディングのヒープバッファオーバーフロー、CVSS 9.8)なども掲載している。


Podのアノテーションがホストを開ける — Kata Containers CVE-2026-44210 を設定から確かめる
https://blog.hashito.biz/2026/08/16/kata-containers-cve-2026-44210-annotation-allowlist-audit/
著者
hashito
作成日
2026年8月16日
著作権