Dev Study
← OWASP Top 10 の群 — 何のリストで、どう作られ、どう読むか
レッスン 10 / 12·約 8 分·第27期 OWASP Top 10 の群

方針を置くまで、クラスタは通す — Kubernetes 2025 K01・K04

リクエストがアプリケーションに届くまで
  1. ブラウザURL入力
  2. DNS名前→IP
  3. ルータ経路選択
  4. ロードバランサ振り分け
  5. Nginx受け口
  6. アプリ処理今ここ
  7. DB保存

番号を読む前に、何を数えた一覧かを読む。今回はデータの裏付けを将来の課題としている一覧から、設定の既定値を扱う2項目を取り上げ、手元のクラスタで確かめます。

まず結論

Kubernetes Top 10 2025 の K01 は「既定のワークロード設定は強くない」、K04 は「クラスタ全体で方針を強制する既定の仕組みが無い」と書きます。k3s v1.37.0 で確かめると、ラベルの無い namespace では privileged: true の Pod がそのまま作られました。

判定の仕組み(PodSecurity admission)は動いていて、既定の水準が「何でも通す privileged」だっただけです。同じ restricted でも、enforce は拒み、warn は警告を返して通します。

? 読む前に予測

k3s v1.37.0 の起動直後、pod-security のラベルが無い namespace に `privileged: true` の Pod を apply すると何が起きたでしょうか。

当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。

抽象原理

何を数えた一覧で、「既定」は何をしているか

まず、この一覧が何を数えたかです。README はこう書きます。

The Top Ten is a prioritized list of these risks. In the future we hope for this to be backed by data collected from organizations varying in maturity and complexity.

優先順位をつけた一覧で、データの裏付けは「将来の希望」です。 集めた件数や割合で並べたとは書かれていません。版の状態も確かめておきます。index と README は 2025 Top 10 Risks now available Feedback welcome. と書き、git log では 2026-03-05 に creates Draft 2025 Kubernetes Top 10、2026-03-18 に remove draft prefix from readme があります。draft の表記は外れましたが、final を名乗る文は見つかりません(確認範囲: リポジトリの index.md・README.md・info.md・2025/ 配下と git log 全150件。owasp.org の他のページは未確認)。

そのうえで2項目を読みます。K01 は既定値を問題にします。

By default, workloads running in a Kubernetes cluster do not have strong security posture, which could make it easier for attackers to compromise applications and expand their compromise to other workloads or the cluster control plane.

避けるべき設定の筆頭が特権コンテナです。

  • Privileged. A privileged container will be able to break out to the underlying host, and this setting should not be used unless absolutely required.

K04 は、それを止める仕組みの既定を問題にします。

While this is powerful, it lacks a default, cluster-wide mechanism for enforcing security policies.

ただし K04 は「admission controller が無い」とは言っていません。主な手段として挙げるのはまさにそれです。

An admission controller is a piece of code that intercepts requests to the Kubernetes API server before an object is created or modified.

その最初の選択肢が Pod Security Admission(PSA)です(The easiest to implement of these is Pod Security Admission (PSA))。kubernetes.io の PSA ページは Stable since Kubernetes v1.25 と表示し、v1.25 の CHANGELOG は見出しで PodSecurityPolicy is Removed, Pod Security Admission graduates to Stable と書きます。同じ版で旧方式が消え、PSA が stable になりました。

置き方は namespace のラベル pod-security.kubernetes.io/<MODE>: <LEVEL> です。水準は Pod Security Standards(ページ表示の Last modified は August 02, 2026)の3つです。

上は PSA ページ(Last modified March 07, 2024)、下は PSS ページ(August 02, 2026。原文の見出しは Profile)の逐語表
MODE Description
enforce Policy violations will cause the pod to be rejected.
audit Policy violations will trigger the addition of an audit annotation to the event recorded in the audit log, but are otherwise allowed.
warn Policy violations will trigger a user-facing warning, but are otherwise allowed.
 
LEVEL Description
Privileged Unrestricted policy, providing the widest possible level of permissions. This policy allows for known privilege escalations.
Baseline Minimally restrictive policy which prevents known privilege escalations. Allows the default (minimally specified) Pod configuration.
Restricted Heavily restricted policy, following current Pod hardening best practices.

拒むのは enforce だけです。warn は使う人への警告で、記録ではありません。 記録を残すのは audit で、行き先は監査ログです。

Pod の作成要求が通るか止まるか(今回の k3s で確かめた範囲)
Pod の作成要求kubectl apply
API サーバが保存する前に
PodSecurity admissionnamespace のラベルから水準とモードを読む
ラベル次第で結果が分かれる
ラベル無しprivileged 水準で評価 → 作成
warnWarning を返して作成
enforceForbidden で拒否
  • ・ラベル無しが privileged で評価されたことは metrics の policy_level で確かめた
  • ・audit も作成される。監査ログの注釈は今回の k3s では見ていない
具体実物

同じ Pod を、ラベルの違う namespace に流す

環境は macOS 上の Docker(Engine 28.4.0、linux/arm64)で動かした rancher/k3s:v1.37.0-k3s1(Server Version v1.37.0+k3s1)、Pod のイメージは busybox:1.37 です。k3s の起動と apply の読み方は第26期で扱います。流したのは securityContext.privileged: true を1つだけ書いた Pod です。

run1.log から priv の行だけを抜粋(sh -x の行、ape・ok の行、ns-baseline の段を省略。残した行は生出力のまま)コマンド出力
=== apply pod-priv.yaml in ns-nolabel
pod/priv created
exit=0
=== apply pod-priv.yaml in ns-warn
Warning: would violate PodSecurity "restricted:latest": privileged (container "c" must not set securityContext.privileged=true), allowPrivilegeEscalation != false (container "c" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "c" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "c" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "c" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
pod/priv created
exit=0
=== apply pod-priv.yaml in ns-audit
pod/priv created
exit=0
=== apply pod-priv.yaml in ns-enforce
Error from server (Forbidden): error when creating "STDIN": pods "priv" is forbidden: violates PodSecurity "restricted:latest": privileged (container "c" must not set securityContext.privileged=true), allowPrivilegeEscalation != false (container "c" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "c" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "c" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "c" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
exit=1
=== 'default' namespace: privileged pod
pod/priv created
exit=0

ラベルの無い namespace と default では、何の表示も無く作られました。restricted は1行を書いた Pod に5項目の違反を返します。 書いていない項目も、許される値を満たさなければ違反です。warn と enforce は同じ一覧を出しますが、前者は作成、後者は exit=1 です。Warning と created の表示の前後は、実行ごとに入れ替わることがありました。

判定が止まっていたわけではありません。同じ実行の metrics です(8行中2行を抜粋)。

kubectl get --raw /metrics | grep '^pod_security_evaluations_total' から2行抜粋コマンド出力
pod_security_evaluations_total{decision="allow",mode="enforce",policy_level="privileged",policy_version="latest",request_operation="create",resource="pod",subresource=""} 13
pod_security_evaluations_total{decision="deny",mode="audit",policy_level="restricted",policy_version="latest",request_operation="create",resource="pod",subresource=""} 2

privileged 水準の allow が13件。うち10件はラベル無し・warn・audit の各3件と default の1件で、残りはシステム側の Pod です。方針が無いのではなく、既定の方針が privileged(何でも通す)でした。 audit の deny 2件は数として増えましたが、k3s の公式ガイドは K3s doesn't enable auditing by default と書いており、監査ログの注釈そのものは今回見ていません。

✓ ここまでの確認

`pod-security.kubernetes.io/warn: restricted` だけを付けた namespace に違反する Pod を apply したとき、実演で起きたことはどれですか。

抽象原理

判定は作成・更新の要求のときだけ行われる(常時監視ではない)

K04 の言い方どおり、admission は before an object is created or modified の要求を止める仕組みです。ここから、ラベルを付けるだけでは届かない場所が2つ出てきます。

1つは、すでに動いている Pod。ラベルは次の作成・更新の要求から効きます。更新も一律ではなく、公式は一部のフィールドだけを審査の対象外とします。

Updates to the following pod fields are exempt from policy checks, meaning that if a pod update request only changes these fields, it will not be denied even if the pod is in violation of the current policy level:

実測(監査役)では、後からラベルを付けた namespace で Running の privileged Pod のイメージを変える kubectl set image は forbidden(exit 1)、kubectl label pod によるラベル追加は通りました(exit 0)。

もう1つは、Pod を作るのが自分ではない場合です。公式はこう書きます。

To help catch violations early, both the audit and warning modes are applied to the workload resources. However, enforce mode is not applied to workload resources, only to the resulting pod objects.

Deployment を apply した時点では警告が出るだけで、拒否は ReplicaSet が Pod を作ろうとした瞬間に、apply した人の画面の外で起きます。

水準の包含にも注意がいります。3水準は cumulative で、allowPrivilegeEscalation の行は Restricted 節にしかありません。ns-baseline では privileged の Pod が baseline:latest の privileged 1項目で拒否され、allowPrivilegeEscalation: true の Pod は作られました。

具体実物

後からラベルを付ける、Deployment で作る

別に起動した k3s で、privileged の Pod が Ready になってから namespace later に enforce=restricted を付けました。

relabel-run3.log から抜粋(sh -x の行・起動待ち・exit 行・Deployment の YAML・deploy の行と各見出しを省略。長い行は途中から(以下省略)に置換。FailedCreate は10行のうち1行)コマンド出力
Warning: existing pods in namespace "later" violate the new PodSecurity enforce level "restricted:latest"
Warning: priv: privileged, allowPrivilegeEscalation != false, unrestricted capabilities, runAsNonRoot != true, seccompProfile
namespace/later labeled
NAME READY STATUS RESTARTS AGE
priv 1/1 Running 0 26s
=== same manifest, apply while the pod still exists (an update with no diff)
pod/priv unchanged
=== same manifest, after deleting the pod (a create)
pod "priv" deleted from later namespace
Error from server (Forbidden): error when creating "STDIN": pods "priv" is forbidden: violates PodSecurity "restricted:latest": privileged (container "c" must not set securityContext.privileged=true), (以下省略)
=== a Deployment whose template is privileged: enforce is not applied to the workload object, only to the pods it makes
Warning: would violate PodSecurity "restricted:latest": privileged (container "busybox" must not set securityContext.privileged=true), (以下省略)
deployment.apps/privdep created
NAME DESIRED CURRENT READY AGE
replicaset.apps/privdep-594cbdcf9b 1 0 0 9s
FailedCreate privdep-594cbdcf9b Error creating: pods "privdep-594cbdcf9b-jvxv5" is forbidden: violates PodSecurity "restricted:latest": privileged (container "busybox" must not set securityContext.privileged=true), (以下省略)

ラベル付けは違反 Pod の名前を並べて成功し、Pod は Running のままです。同じマニフェストの再 apply は差分の無い更新なので unchanged、消してから流すと作成になり拒否されました。Deployment は created と出ながら、ReplicaSet の CURRENT は 0 です。

✓ ここまでの確認

enforce=restricted の namespace に、template が privileged の Deployment を apply しました。実演の結果はどれですか。

⇄ 2つを見比べる
具体例 A

enforce=restricted

違反の一覧を持つ Forbidden が返り、exit=1。Pod は作られません。ただし相手は Pod の作成要求だけで、既存の Pod と Deployment 自体は止めません。

ns-enforce(run1.log、拒否文は途中で省略)コマンド出力
Error from server (Forbidden): error when creating "STDIN": pods "priv" is forbidden: violates PodSecurity "restricted:latest": privileged (...), (以下省略)
exit=1
具体例 B

warn=restricted

同じ一覧が Warning として出て、Pod は作られ exit=0。Running まで進みます。警告は apply した人の画面に出るだけで、画面を見なければ残りません。

ns-warn(run1.log、警告文は途中で省略)コマンド出力
Warning: would violate PodSecurity "restricted:latest": privileged (...), (以下省略)
pod/priv created
exit=0

K04 は「まず audit か warn から始めよ」と勧めます。warn だけを付けた namespace を「restricted を入れた」と報告してよいでしょうか。

exit の値と、その後 Pod がどうなったかを見てください。

この章のまとめ

  • Kubernetes Top 10 2025 は 優先順位の一覧で、データの裏付けは将来の希望。draft 表記は外れたが、確認範囲に final の表明は無い。
  • K01 は既定のワークロード設定が強くないこと、K04 は方針を強制する クラスタ全体の既定の仕組み が無いことを挙げる。
  • k3s v1.37.0 ではラベル無しの namespace で privileged の Pod が作られた。判定は動いていて、既定の水準が privileged。
  • PSA は v1.25 で stable(PodSecurityPolicy は同じ版で削除)。拒むのは enforce だけ。warn は利用者向けの警告で、記録ではない。 audit の記録は今回の k3s では見ていない。
  • 判定は作成・更新の要求時のみ。動いている Pod を止めはしない。enforce は Deployment ではなく作られる Pod に効く。
  • 関連クイズの security-owasp-top10-8・-18 は Web 2021 の A05 の番号で、2025 では A02:2025。

自分の現場で確かめる

読んだだけでは身につきません。手元の環境で実際に見てみてください。

環境:

理解度チェック

読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。

問題 1 / 3正解: 0

OWASP Kubernetes Top 10 2025 は、自分の順位の根拠について何と書いていますか(確認範囲: リポジトリの README と index)。

用語集(3語)
Pod Security Admission
namespace のラベルに従い、作成される Pod を Pod Security Standards の水準で判定する組み込みの admission controller。Kubernetes v1.25 で stable。
Pod Security Standards
privileged・baseline・restricted の3水準。公式は累積的(cumulative)で、緩いものから厳しいものへ並ぶと書く。
enforce / warn / audit
水準の置き方。enforce は拒否、warn は使う人への警告を返して通す、audit は監査ログのイベントに注釈を付けて通す。