# Kubernetes ValidatingWebhookConfiguration

{{#include ../../banners/hacktricks-training.md}}

**The original author of this page is** [**Guillaume**](https://www.linkedin.com/in/guillaume-chapela-ab4b9a196)

## Definition

`ValidatingWebhookConfiguration` is a Kubernetes resource that registers one or more validating admission webhooks. These webhooks receive AdmissionReview requests from the API server after authentication and authorization, but before the object is persisted.

Validating webhooks can reject a request. Mutating webhooks, configured with `MutatingWebhookConfiguration`, can change the object first. Security reviews should usually inspect both resources because a malicious or weak mutating webhook can rewrite workloads, while a validating webhook or policy engine can block or allow them.

## Purpose

The purpose of a `ValidatingWebhookConfiguration` is to define when the API server should call a validating webhook and how it should handle the webhook result. The important security question is not only "is a policy installed?", but also:

- Which API groups, resources, operations, and scopes does it match?
- Which namespaces or objects are excluded by selectors?
- Does `matchConditions` skip any request classes?
- Does `failurePolicy` fail open with `Ignore` or fail closed with `Fail`?
- Is the webhook service reachable, trusted by the configured `caBundle`, and run by a highly privileged service account?
- Does the policy engine also expose exception resources, excluded users, or excluded groups?

**Example**

Here is an example of a ValidatingWebhookConfiguration:

```yaml
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
  name: example-validation-webhook
webhooks:
  - name: pods.example.local
    admissionReviewVersions: ["v1"]
    sideEffects: None
    failurePolicy: Fail
    timeoutSeconds: 5
    clientConfig:
      service:
        namespace: webhook-system
        name: example-validation-webhook
        path: /validate
      caBundle: <base64-ca-bundle>
    rules:
      - apiGroups: [""]
        apiVersions: ["v1"]
        operations: ["CREATE", "UPDATE"]
        resources: ["pods"]
        scope: "Namespaced"
    namespaceSelector:
      matchExpressions:
        - key: kubernetes.io/metadata.name
          operator: NotIn
          values: ["kube-system"]
```

The main difference between a ValidatingWebhookConfiguration and policies :

<figure><img src="../../images/Kyverno.png" alt=""><figcaption><p>Kyverno.png</p></figcaption></figure>

- **ValidatingWebhookConfiguration (VWC)** : A Kubernetes resource that defines a validating webhook, which is a server-side component that validates incoming Kubernetes API requests against a set of predefined rules and constraints.
- **Kyverno ClusterPolicy**: A policy definition that specifies a set of rules and constraints for validating and enforcing Kubernetes resources, such as pods, deployments, and services

## Enumeration

```
$ kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations
$ kubectl get validatingwebhookconfiguration <name> -o yaml
$ kubectl get mutatingwebhookconfiguration <name> -o yaml
$ kubectl get svc,deploy,pod -A | grep -i webhook
```

Fields to inspect:

- `rules`: Check covered API groups, versions, resources, subresources, operations, and scope.
- `namespaceSelector` / `objectSelector`: Look for namespaces or labels that exclude resources from policy.
- `matchConditions`: CEL expressions can intentionally or accidentally skip requests.
- `failurePolicy`: `Ignore` lets requests continue if the webhook fails; `Fail` blocks them.
- `sideEffects`: Webhooks with side effects may not support dry-run testing.
- `timeoutSeconds`: Very short timeouts combined with `Ignore` can become fail-open behavior.
- `clientConfig`: Review whether the webhook points to an in-cluster Service or external URL, and inspect the backing workload and service account.
- `reinvocationPolicy`: Mutating webhooks may be reinvoked when later mutation changes the object.

### Native CEL admission policies

Modern clusters can also enforce admission logic with native policy objects in `admissionregistration.k8s.io`, not only with webhook configurations. `ValidatingAdmissionPolicy` is an in-process CEL-based alternative to validating webhooks and is only active when a `ValidatingAdmissionPolicyBinding` selects it. `MutatingAdmissionPolicy` is stable in Kubernetes v1.36 and is activated by `MutatingAdmissionPolicyBinding` for CEL-generated mutations.

Enumerate them with:

```bash
kubectl api-resources --api-group=admissionregistration.k8s.io -o wide
kubectl get validatingadmissionpolicies,validatingadmissionpolicybindings
kubectl get mutatingadmissionpolicies,mutatingadmissionpolicybindings 2>/dev/null || true
kubectl get validatingadmissionpolicy <name> -o yaml
kubectl get validatingadmissionpolicybinding <name> -o yaml
```

Security checks:

- A policy without a binding does not enforce anything.
- `validationActions` on the binding decides whether validation failures are denied, warned, audited, or only recorded.
- `failurePolicy: Ignore` lets CEL evaluation errors or misconfiguration fail open.
- `matchConstraints`, `matchConditions`, `namespaceSelector`, and `objectSelector` can exclude sensitive requests.
- `paramKind` and `paramRef` can make ConfigMaps or CRD-backed parameter objects part of the policy boundary; check who can modify those parameter objects.
- Writes to policies, bindings, and parameter resources should be treated like privileged admission-control changes.

### Abusing Kyverno and Gatekeeper VWC

As we can see all operators installed have at least one ValidatingWebHookConfiguration(VWC).

**Kyverno** and **Gatekeeper** are both Kubernetes policy engines that provide a framework for defining and enforcing policies across a cluster.

Exceptions refer to specific rules or conditions that allow a policy to be bypassed or modified under certain circumstances but this is not the only way !

For **kyverno**, as you as there is a validating policy, the webhook `kyverno-resource-validating-webhook-cfg` is populated.

For Gatekeeper, there is `gatekeeper-validating-webhook-configuration` YAML file.

Both come from with default values but the Administrator teams might updated those 2 files.

### Use Case

```bash
$ kubectl get validatingwebhookconfiguration kyverno-resource-validating-webhook-cfg -o yaml
```

Now, identify the following output :

```yaml
namespaceSelector:
  matchExpressions:
    - key: kubernetes.io/metadata.name
      operator: NotIn
      values:
        - default
        - TEST
        - YOYO
        - kube-system
        - MYAPP
```

Here, `kubernetes.io/metadata.name` refers to the namespace name label. Namespaces with names in the `values` list will be excluded from the policy:

Check namespaces existence. Sometimes, due to automation or misconfiguration, some namespaces might have not been created. If you have permission to create namespace, you could create a namespace with a name in the `values` list and policies won't apply your new namespace.

The goal of this attack is to exploit **misconfiguration** inside VWC in order to bypass operators restrictions and then elevate your privileges with other techniques

Other common bypass or abuse patterns:

- An `objectSelector` that allows users to add an opt-out label to their own objects.
- `failurePolicy: Ignore` on security-critical validation, especially when the webhook Service has no endpoints or unreliable networking.
- Policy engine exceptions for users, groups, service accounts, namespaces, or roles that are broader than intended.
- Missing coverage for workload controller templates, `pods/ephemeralcontainers`, `pods/exec`, custom resources, or update operations.
- Write access to `validatingwebhookconfigurations`, `mutatingwebhookconfigurations`, Gatekeeper constraints, Kyverno policies, or exception resources.
- A malicious mutating webhook that injects containers, changes images, mounts secrets, adds tolerations, or changes service account selection before validation.

Remember that admission only protects requests that pass through the API server admission chain. Static Pods, node-local runtime socket access, direct kubelet abuse, and direct etcd access are different trust paths and need separate hardening and monitoring.

{{#ref}}
abusing-roles-clusterroles-in-kubernetes/
{{#endref}}

## References

- [https://github.com/open-policy-agent/gatekeeper](https://github.com/open-policy-agent/gatekeeper)
- [https://kyverno.io/](https://kyverno.io/)
- [https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/)
- [https://kubernetes.io/docs/concepts/cluster-administration/admission-webhooks-good-practices/](https://kubernetes.io/docs/concepts/cluster-administration/admission-webhooks-good-practices/)
- [https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/](https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/)
- [https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/](https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/)
- [https://kubernetes.io/docs/reference/using-api/cel/](https://kubernetes.io/docs/reference/using-api/cel/)



{{#include ../../banners/hacktricks-training.md}}
