Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions pkg/builtinchecks/yamls/aggregate-to-admin-escalation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: aggregate-to-admin-escalation
description: >-
ClusterRole with an aggregate-to-admin, aggregate-to-edit, or
aggregate-to-view label grants escalation-capable verbs on privileged
resources. Kubernetes automatically merges these rules into the admin,
edit, or view ClusterRole, meaning every namespace admin inherits them.
remediation: >-
Review whether the aggregated permissions are necessary. Remove escalation
verbs (create, delete, patch, *) on privileged resources (secrets, roles,
clusterroles, clusterrolebindings) from aggregate-labeled ClusterRoles.
scope:
objectKinds:
- ClusterRole
template: cel-expression
params:
check: >
has(object.metadata.labels) &&
(
(has(object.metadata.labels['rbac.authorization.k8s.io/aggregate-to-admin']) &&
object.metadata.labels['rbac.authorization.k8s.io/aggregate-to-admin'] == 'true') ||
(has(object.metadata.labels['rbac.authorization.k8s.io/aggregate-to-edit']) &&
object.metadata.labels['rbac.authorization.k8s.io/aggregate-to-edit'] == 'true') ||
(has(object.metadata.labels['rbac.authorization.k8s.io/aggregate-to-view']) &&
object.metadata.labels['rbac.authorization.k8s.io/aggregate-to-view'] == 'true')
) &&
object.rules.exists(r,
r.verbs.exists(v, v == '*' || v == 'create' || v == 'delete' || v == 'patch') &&
r.resources.exists(res, res == '*' || res == 'secrets' || res == 'roles' ||
res == 'clusterroles' || res == 'clusterrolebindings')
Comment thread
coderabbitai[bot] marked this conversation as resolved.
) ? 'aggregate-labeled ClusterRole grants escalation verbs on privileged resources — inherited by every namespace admin/editor' : ''
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: approve-signers-without-resource-names
description: >-
Roles granting the 'approve' verb on certificate signers without
resourceNames restriction allow approval of certificates from any
signer, including cluster-scoped signers.
remediation: >-
Add resourceNames to restrict which certificate signers can be approved.
scope:
objectKinds:
- Role
- ClusterRole
template: cel-expression
params:
check: >
object.rules.exists(r,
r.resources.exists(res, res == 'signers' || res == '*') &&
r.verbs.exists(v, v == 'approve' || v == '*') &&
(!has(r.resourceNames) || r.resourceNames.size() == 0)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
) ? 'approve verb on signers without resourceNames restriction' : ''
21 changes: 21 additions & 0 deletions pkg/builtinchecks/yamls/bind-verb-in-role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: bind-verb-in-role
description: >-
Roles granting the 'bind' verb on roles, clusterroles, rolebindings,
or clusterrolebindings allow the holder to create bindings to any role,
including roles with more permissions than they currently have.
remediation: >-
Remove the 'bind' verb unless the workload is a controller that
legitimately manages RBAC bindings. If required, scope with
resourceNames to limit which roles can be bound.
scope:
objectKinds:
- Role
- ClusterRole
template: cel-expression
params:
check: >
object.rules.exists(r,
r.resources.exists(res, res == 'roles' || res == 'clusterroles' ||
res == 'rolebindings' || res == 'clusterrolebindings' || res == '*') &&
r.verbs.exists(v, v == 'bind' || v == '*')
) ? 'bind verb on RBAC resources allows privilege escalation via arbitrary bindings' : ''
Comment thread
coderabbitai[bot] marked this conversation as resolved.
20 changes: 20 additions & 0 deletions pkg/builtinchecks/yamls/deletecollection-verb-in-role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: deletecollection-verb-in-role
description: >-
Role grants deletecollection verb, which allows bulk deletion of all
resources of a type in a single API call. Unlike delete (per-resource),
deletecollection enables rapid, complete resource destruction.
remediation: >-
Remove deletecollection unless the workload legitimately needs to bulk-delete
resources. Use delete instead for per-resource deletion.
scope:
objectKinds:
- Role
- ClusterRole
template: cel-expression
params:
check: >
object.rules.exists(r,
r.verbs.exists(v, v == 'deletecollection') &&
r.resources.exists(res, res == '*' || res == 'secrets' || res == 'pods' ||
res == 'deployments' || res == 'configmaps' || res == 'namespaces')
) ? 'deletecollection verb allows bulk resource destruction in a single API call' : ''
Comment thread
coderabbitai[bot] marked this conversation as resolved.
20 changes: 20 additions & 0 deletions pkg/builtinchecks/yamls/escalate-verb-in-role.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: escalate-verb-in-role
description: >-
Roles granting the 'escalate' verb on roles or clusterroles allow the
holder to create or modify roles with permissions exceeding their own,
bypassing Kubernetes RBAC escalation protection.
remediation: >-
Remove the 'escalate' verb unless the workload is a controller that
legitimately manages RBAC resources. If required, scope with
resourceNames to limit which roles can be escalated.
scope:
objectKinds:
- Role
- ClusterRole
template: cel-expression
params:
check: >
object.rules.exists(r,
r.resources.exists(res, res == 'roles' || res == 'clusterroles' || res == '*') &&
r.verbs.exists(v, v == 'escalate' || v == '*')
) ? 'escalate verb on roles/clusterroles allows privilege escalation' : ''
Comment thread
coderabbitai[bot] marked this conversation as resolved.
19 changes: 19 additions & 0 deletions pkg/builtinchecks/yamls/impersonate-without-resource-names.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: impersonate-without-resource-names
description: >-
Roles granting the 'impersonate' verb on users, groups, or serviceaccounts
without a resourceNames restriction allow any bearer of the bound SA token
to impersonate system:masters and gain cluster-admin equivalent access.
remediation: >-
Add a resourceNames list to restrict which identities can be impersonated,
or remove the impersonate verb if it is not needed.
scope:
objectKinds:
- Role
- ClusterRole
template: cel-expression
params:
check: >
object.rules.exists(r,
r.verbs.exists(v, v == 'impersonate' || v == '*') &&
(!has(r.resourceNames) || r.resourceNames.size() == 0)
Comment thread
coderabbitai[bot] marked this conversation as resolved.
) ? 'impersonate verb granted without resourceNames restriction — allows system:masters impersonation' : ''
19 changes: 19 additions & 0 deletions pkg/builtinchecks/yamls/webhook-failure-policy-ignore.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: webhook-failure-policy-ignore
description: >-
Admission webhook with failurePolicy: Ignore silently allows all requests
when the webhook is unavailable — attackers can bypass validation by DoSing
the webhook endpoint.
remediation: >-
Set failurePolicy to Fail. Ensure webhook availability with proper
health checks, replicas, and PodDisruptionBudgets.
scope:
objectKinds:
- Any
template: cel-expression
params:
check: >
(object.kind == 'ValidatingWebhookConfiguration' ||
object.kind == 'MutatingWebhookConfiguration') &&
object.webhooks.exists(w,
has(w.failurePolicy) && w.failurePolicy == 'Ignore'
Comment thread
coderabbitai[bot] marked this conversation as resolved.
) ? 'admission webhook with failurePolicy: Ignore fails open — bypass via webhook DoS' : ''
19 changes: 19 additions & 0 deletions pkg/builtinchecks/yamls/wildcard-resource-verb-combo.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: wildcard-resource-verb-combo
description: >-
ClusterRole rule with wildcard verbs on wildcard resources is functionally
equivalent to cluster-admin. Unlike a named cluster-admin binding, this
pattern is not caught by the cluster-admin-role-binding check.
remediation: >-
Replace wildcard grants with explicit resource and verb lists scoped to
what the workload actually needs.
scope:
objectKinds:
- ClusterRole
template: cel-expression
params:
check: >
object.rules.exists(r,
r.apiGroups.exists(g, g == '*' || g == '') &&
r.resources.exists(res, res == '*') &&
r.verbs.exists(v, v == '*')
) ? 'rule grants wildcard verbs on wildcard resources — functionally cluster-admin' : ''
Comment thread
coderabbitai[bot] marked this conversation as resolved.
22 changes: 22 additions & 0 deletions tests/checks/aggregate-to-admin-escalation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: dont-fire
labels:
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rules:
- apiGroups: ["example.com"]
resources: ["widgets"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fire-aggregate-admin-secrets
labels:
rbac.authorization.k8s.io/aggregate-to-admin: "true"
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create", "delete"]
19 changes: 19 additions & 0 deletions tests/checks/approve-signers-without-resource-names.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: dont-fire
rules:
- apiGroups: ["certificates.k8s.io"]
resources: ["signers"]
verbs: ["approve"]
resourceNames: ["example.com/my-signer"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fire-approve-no-restriction
rules:
- apiGroups: ["certificates.k8s.io"]
resources: ["signers"]
verbs: ["approve"]
18 changes: 18 additions & 0 deletions tests/checks/bind-verb-in-role.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: dont-fire
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["roles"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fire-bind
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles"]
verbs: ["bind"]
18 changes: 18 additions & 0 deletions tests/checks/deletecollection-verb-in-role.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: dont-fire
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fire-deletecollection
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["deletecollection"]
28 changes: 28 additions & 0 deletions tests/checks/escalate-verb-in-role.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: dont-fire
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["roles"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fire-escalate
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["roles"]
verbs: ["escalate"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: fire-wildcard-verb-on-clusterroles
namespace: default
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["clusterroles"]
verbs: ["*"]
37 changes: 37 additions & 0 deletions tests/checks/impersonate-without-resource-names.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: dont-fire
rules:
- apiGroups: [""]
resources: ["users"]
verbs: ["impersonate"]
resourceNames: ["jane"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: dont-fire-no-impersonate
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fire-impersonate-no-restriction
rules:
- apiGroups: [""]
resources: ["users", "groups", "serviceaccounts"]
verbs: ["impersonate"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fire-wildcard-verb
rules:
- apiGroups: [""]
resources: ["users"]
verbs: ["*"]
28 changes: 28 additions & 0 deletions tests/checks/webhook-failure-policy-ignore.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: dont-fire
webhooks:
- name: validate.example.com
failurePolicy: Fail
clientConfig:
service:
name: webhook-service
namespace: default
admissionReviewVersions: ["v1"]
sideEffects: None
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
name: fire-ignore-policy
webhooks:
- name: validate.example.com
failurePolicy: Ignore
clientConfig:
service:
name: webhook-service
namespace: default
admissionReviewVersions: ["v1"]
sideEffects: None
18 changes: 18 additions & 0 deletions tests/checks/wildcard-resource-verb-combo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: dont-fire
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fire-triple-wildcard
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
Loading