CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



GHSA-W54X-R83C-X79Q
0.00.04%

CVE-2026-23634: Pepr's Generous Gift of Cluster Admin

Alon Barad
Alon Barad
Software Engineer

Feb 18, 2026·5 min read·2 visits

No Known Exploit

Executive Summary (TL;DR)

Pepr, a Kubernetes middleware framework, defaulted to granting `cluster-admin` privileges to its modules prior to version 1.0.5. This means any code running in a Pepr module—including third-party dependencies—had full control over the cluster by default. The fix is largely advisory, adding warnings rather than enforcing restrictions.

In the race to improve Developer Experience (DX), security often gets left in the dust. This is the story of CVE-2026-23634, where the Pepr Kubernetes framework decided the best way to help you get started was to silently grant your code absolute power over the entire cluster. It's a classic case of 'secure defaults' being sacrificed on the altar of 'it just works'.

The Hook: Unlimited Power, Zero Effort

In the world of Kubernetes, the cluster-admin role is the Holy Grail. It is the root user, the master key, the one ring to rule them all. If you have it, you can read every secret, delete every namespace, and essentially hold the entire infrastructure hostage. Security 101 dictates that you never give this permission out unless absolutely necessary, and certainly not by default.

Then came Pepr. Pepr is a slick TypeScript framework designed to make Kubernetes middleware easy. Instead of writing complex controllers in Go, you write simple TS modules to mutate resources. It’s elegant, it’s modern, and prior to version 1.0.5, it was incredibly dangerous.

To ensure a "frictionless" onboarding experience, Pepr decided that the path of least resistance was the path of most privilege. When a developer initialized a new module, the framework automatically generated RBAC manifests binding that module's ServiceAccount to cluster-admin. No questions asked, no warnings given. You wanted to write a simple label mutator? Congratulations, you just deployed a pod with the ability to nuke the cluster.

The Flaw: DX vs. PoLP

The root cause here isn't a buffer overflow or a logic error in a parser. It's a philosophical failure. The vulnerability (CWE-272) is a violation of the Principle of Least Privilege (PoLP). The developers prioritized the "getting started" experience over security boundaries.

Under the hood, when you ran npx pepr init, the CLI generated a ClusterRoleBinding. In a secure world, this binding would be scoped—perhaps allowing the module to watch Pods and patch them, and nothing else. In Pepr's world, it effectively generated this:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: pepr-system-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin # <--- The keys to the kingdom
subjects:
- kind: ServiceAccount
  name: pepr-system
  namespace: pepr-system

This is the configuration equivalent of leaving your front door unlockable because keys are "too hard" for new homeowners to understand. While the CVSS score is technically 0.0 (because the vendor argues this is a configuration choice), the actual risk in a production environment is Critical.

The Code: The "Fix" That Just Yells at You

The remediation for this CVE is fascinating because it doesn't actually stop you from shooting yourself in the foot; it just puts a warning label on the gun. The maintainers decided that breaking backward compatibility or forcing users to understand RBAC immediately was too high a cost.

Here is the essence of the patch in commit d4675a662b8602fcde7e4bf603432f2f133b1fd1. They didn't remove the admin capability; they just added a Log.warn.

Before (v1.0.4): The CLI would silently generate the admin binding. Silence is consent.

After (v1.0.5):

// src/lib/assets/rbac.ts
 
if (config.rbacMode === 'admin') {
  Log.warn(
    `The default RBAC mode (admin) generates a ClusterRole with cluster-admin level ` +
    `permissions for the hello-pepr capability. This is intended for demo/POC purposes only ` +
    `and should NOT be used in production.`
  );
  // Proceed to generate the admin binding anyway...
}

While they also hardened documentation to strongly suggest using --rbac-mode=scoped, the default behavior arguably remains a trap for the unwary. It relies on developers actually reading their terminal output during initialization—a bold assumption in the age of npm install && go grab coffee.

The Exploit: Supply Chain Hijacking

Since this is a privilege escalation primitive, let's look at how an attacker exploits it. The vector here is likely Supply Chain Compromise. Pepr modules are just Node.js projects. They pull in dependencies from npm.

Imagine a developer creates a Pepr module to enforce some naming conventions. They install a helper library: npm install color-string. Unknown to them, color-string has been typo-squatted or hijacked.

Because the Pepr module runs as cluster-admin, that malicious npm package inherits those permissions immediately upon startup. It doesn't need a kernel exploit or a container escape. It just needs to make one HTTP request.

Attack Flow

The malicious code simply reads the token mounted at /var/run/secrets/kubernetes.io/serviceaccount/token and sends it to an external server. The attacker now has a persistent, valid cluster-admin token. They can deploy crypto miners, steal database credentials, or ransom the entire cluster.

The Fix: RTFM (Read The Manual)

Since the software doesn't force your hand, you have to be the adult in the room. The fix involves both upgrading and changing your workflow.

First, upgrade to Pepr v1.0.5+. This ensures you at least get the warnings and the documentation references. Second, stop using defaults. When you initialize or build a module intended for anywhere near a production cluster, you must explicitly scope the RBAC.

The Command You Should Be Running:

npx pepr build --rbac-mode=scoped

This forces Pepr to generate a Role that only includes the permissions you explicitly defined in your capabilities. If your module only needs to read ConfigMaps, that's all it gets.

Finally, audit your cluster. Run the following command to see if you've already fallen into the trap:

kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin") | .metadata.name'

If you see pepr-system or similar auto-generated names in that list, you have some urgent refactoring to do.

Official Patches

Defense UnicornsOfficial GitHub Security Advisory

Fix Analysis (1)

Technical Appendix

CVSS Score
0.0/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N
EPSS Probability
0.04%
Top 87% most exploited

Affected Systems

Pepr Middleware FrameworkKubernetes Clusters running default Pepr modules

Affected Versions Detail

Product
Affected Versions
Fixed Version
Pepr
Defense Unicorns
< 1.0.51.0.5
AttributeDetail
CWE IDCWE-272 (Least Privilege Violation)
CVSS Score0.0 (Functional Critical)
Attack VectorConfiguration / Supply Chain
Privileges RequiredNone (if supply chain compromised)
ImpactFull Cluster Compromise
Fix TypeAdvisory / Warning

MITRE ATT&CK Mapping

T1078Valid Accounts
Defense Evasion
T1611Escape to Host
Privilege Escalation
T1552Unsecured Credentials
Credential Access
CWE-272
Least Privilege Violation

The software does not perform a privilege check or uses a default setting that grants excessive privileges.

Known Exploits & Detection

TheorySupply chain compromise of Pepr module dependencies allows immediate cluster-admin access.

Vulnerability Timeline

Internal hardening begins
2026-01-06
Fix commit d4675a6 pushed (warnings added)
2026-01-15
Public disclosure (GHSA and CVE)
2026-01-16

References & Sources

  • [1]GHSA-w54x-r83c-x79q
  • [2]CWE-272: Least Privilege Violation
Related Vulnerabilities
CVE-2026-23634

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.