Skip to content

CVE-2026-58165: Verified Reproduction

CVE-2026-58165: OpenZiti privilege escalation via overpermissive enrollment creation

CVE-2026-58165 is verified against the affected target. Vulnerability class: Privilege Escalation. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00237.

REPRO-2026-00237 Privilege Escalation Jul 6, 2026 CVE entry .txt
Severity
HIGH
CVSS
8.8
Confidence
HIGH
Reproduced in
22m 39s
Tool calls
211
Spend
$2.98
01 · Overview

What Is CVE-2026-58165?

CVE-2026-58165 is a high-severity privilege escalation vulnerability in the OpenZiti controller (through version 2.0.0) where an authenticated non-admin identity with fine-grained enrollment-management permissions can create enrollments for any identity, including the default admin, and use them to obtain admin access. Pruva reproduced it (reproduction REPRO-2026-00237).

02 · Severity & CVSS

CVE-2026-58165 Severity & CVSS Score

CVE-2026-58165 is rated high severity, with a CVSS base score of 8.8 out of 10.

HIGH threat level
8.8 / 10 CVSS base
Weakness CWE-862 — Missing Authorization

High — serious impact or readily exploitable. Prioritize remediation.

How to Reproduce CVE-2026-58165

$ pruva-verify REPRO-2026-00237
or curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00237/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh
Run in a VM or disposable container. This exploits a real vulnerability.
06 · Proof of Reproduction

Proof of Reproduction for CVE-2026-58165

Privilege escalation — reproduced
  • reached the target end-to-end
  • full exploit chain demonstrated
  • on the real production code path
  • high confidence
  • the upstream fix blocks the same trigger
Trigger

non-admin management API session with enrollment permission; POST /enrollments body targeting an admin identityId

Attack chain
  1. OpenZiti controller management API /edge/management/v1/enrollments
  2. Create
  3. unauthenticated /enroll redeem
  4. admin management API session
Runnable proof: reproduction_steps.sh
Captured evidence: vulnerable testfixed test
How the agent worked 539 events · 211 tool calls · 23 min
23 minDuration
211Tool calls
161Reasoning steps
539Events
1Dead-ends
Agent activity over 23 min
Support
20
Hypothesis
2
Repro
197
Judge
22
Variant
294
0:0022:39

Root Cause and Exploit Chain for CVE-2026-58165

Versions: OpenZiti through 2.0.0 (vulnerable commit c2e6c8ee3).Fixed: Commit 3027fdffd ("Prevent enrollment-based privilege escalation to admin identities. Fixes #4010").

OpenZiti through 2.0.0 allows an authenticated non-admin identity that has been granted fine-grained enrollment-management permissions to create, read, refresh, and delete OTT enrollments for any identity, including identities with the isAdmin flag. Because an enrollment mints the one-time token (and JWT) used to authenticate as the target identity, a non-admin with enrollment permission can create an enrollment for an admin identity, redeem it through the unauthenticated client /enroll endpoint, and obtain a client certificate that authenticates as the targeted admin. This yields full administrative control over the controller and the zero-trust overlay it manages.

  • Product/component: OpenZiti controller (ziti-controller), specifically the enrollment management REST API (/edge/management/v1/enrollments).
  • Affected versions: OpenZiti through 2.0.0 (vulnerable commit c2e6c8ee3).
  • Fixed version: Commit 3027fdffd ("Prevent enrollment-based privilege escalation to admin identities. Fixes #4010").
  • Risk level: High. Any authenticated non-admin user with the enrollment permission can escalate to an arbitrary admin identity, including the default administrator, bypassing all role-based access controls.
  • Consequences: Full administrative compromise of the controller, including ability to create/modify identities, services, policies, routers, and CA configurations.

Impact Parity

  • Disclosed/claimed maximum impact: Privilege escalation from a low-privileged identity to an admin identity via enrollment creation.
  • Reproduced impact from this run: Confirmed. A non-admin identity with only enrollment permission successfully created an OTT enrollment for a newly created admin identity, redeemed the enrollment, and used the resulting certificate to perform an admin-only operation (creating another identity through the management API). The same workflow on the fixed commit is rejected with HTTP 401 Unauthorized.
  • Parity: full.
  • Not demonstrated: N/A. The reproduction reaches the claimed administrative impact end-to-end.

Root Cause

The enrollment creation, read, refresh, and delete handlers in controller/internal/routes/enrollment_router.go only verified that the caller had the enrollment entity permission and that the target identity existed. They did not check whether the target identity was an administrator or whether the caller was authorized to manage enrollments on behalf of an admin identity. Specifically, EnrollmentRouter.Create called MapCreate without any guard against admin-targeted enrollments.

The fix (commit 3027fdffd) adds two helpers:

  • allowNonAdminEnrollmentForIdentity — returns an unauthorized error when a non-admin tries to create an enrollment targeting an admin identity.
  • allowNonAdminAccessToEnrollment — returns an unauthorized error when a non-admin tries to read, refresh, or delete an enrollment that belongs to an admin identity.

The list handler is also modified to filter out admin-identity enrollments for non-admin callers by adding not (identity.isAdmin = true) to the query predicate.

Reproduction Steps

The reproduction is fully automated in bundle/repro/reproduction_steps.sh. The script performs the following steps:

  1. Reads bundle/project_cache_context.json and uses the prepared project cache directory (/data/pruva/project-cache/92b8f1e5-395e-41fd-8f92-ae0d5f2888dc).
  2. Installs Go 1.26.4 into the project cache if it is not already present.
  3. Clones (or reuses) the openziti/ziti repository at <project_cache_dir>/repo.
  4. Resolves the vulnerable commit (3027fdffd^) and the fixed commit (3027fdffd).
  5. Verifies that the fixed commit contains the patch to controller/internal/routes/enrollment_router.go and that the vulnerable commit does not.
  6. Copies bundle/repro/cve_2026_58165_repro_test.go into the repo's tests/ directory at runtime.
  7. Runs the Go integration test Test_CVE202658165_AdminEnrollmentEscalation against the vulnerable commit, capturing the result to bundle/repro/vulnerable_result.json.
  8. Runs the same test against the fixed commit, capturing the result to bundle/repro/fixed_result.json.
  9. Compares the two results and writes bundle/repro/runtime_manifest.json.

Expected evidence of reproduction:

  • bundle/repro/vulnerable_result.json shows "vulnerable": true, "create_status_code": 201, and a non-empty created_identity_id proving an admin-only operation succeeded.
  • bundle/repro/fixed_result.json shows "fixed": true, "create_status_code": 401, and the response body contains "non-admins may not manage enrollments for admin identities".

Evidence

  • bundle/logs/reproduction_steps.log — full script output with commit resolution, test execution, and summary.
  • bundle/logs/vulnerable_test.log — Go test output for the vulnerable commit.
  • bundle/logs/fixed_test.log — Go test output for the fixed commit.
  • bundle/repro/vulnerable_result.json — captured result proving the escalation succeeded.
  • bundle/repro/fixed_result.json — captured result proving the escalation is blocked.
  • bundle/repro/runtime_manifest.json — runtime evidence manifest describing the API surface and artifacts.

Key excerpt from the vulnerable result:

{
  "vulnerable": true,
  "create_status_code": 201,
  "created_identity_id": "...",
  "notes": "non-admin created an enrollment for an admin identity, redeemed it, and performed an admin-only operation"
}

Key excerpt from the fixed result:

{
  "fixed": true,
  "create_status_code": 401,
  "create_response_body": "{\"error\":{\"cause\":{\"code\":\"UNHANDLED\",\"message\":\"non-admins may not manage enrollments for admin identities\"},\"code\":\"UNAUTHORIZED\",...}}",
  "notes": "non-admin create enrollment for admin identity returned 401 (fixed behavior)"
}

Environment captured during the run:

  • Go 1.26.4 (installed from https://go.dev/dl/go1.26.4.linux-amd64.tar.gz)
  • Repository: github.com/openziti/ziti
  • Vulnerable commit: c2e6c8ee3da42321ef22442c8d25d0413caf4a4f
  • Fixed commit: 3027fdffd3e57884487b7c46e5e669cfbc8becdf

Recommendations / Next Steps

  • Upgrade: Upgrade the OpenZiti controller to a build that includes commit 3027fdffd or later.
  • Temporary mitigation: Remove the enrollment permission from any non-admin identities or role attributes until the patch is deployed.
  • Testing: Add the regression test tests/permissions_enrollment_test.go::Test_Permissions_Enrollment_AdminIdentityEscalation (introduced in the fix) to CI to prevent future regressions.
  • Audit: Review other entity-level permissions for similar authorization gaps where a non-admin can manage resources that belong to admin identities.

Additional Notes

  • The reproduction script was executed twice consecutively and produced the same vulnerable/fixed divergence both times, confirming idempotency.
  • The Go test harness starts a real OpenZiti controller using the checked-out source code, so the reproduction exercises the actual product code path rather than a mock.
  • The custom test file is copied into the repo at runtime and removed after each run to avoid permanently altering the source checkout.
  • Build outputs are cached in the durable project cache, so subsequent runs reuse the already-installed Go toolchain and already-cloned repository.

CVE-2026-58165 Reproduction Transcript

The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.

Full session Replay every step — scrub the timeline or play it back.

Event 1/40
0:001:53
0:00
session startedaccounts/fireworks/models/kimi-k2p7-code · CVE-2026-58165 · REPRO-20
0:04
0:06
web search
0:09
0:11
web search
0:12
0:15
0:16
web search
0:37
0:41
0:42
web search
0:53
0:53
extract_facts
no facts extracted
0:54
0:54
0:54
supportrepro
1:33
1:35
1:35
1:35
1:37
1:37
1:37
1:38
1:38
1:50
1:51
web search
1:53
08 · How to Fix

How to Fix CVE-2026-58165

Coming soon

Step-by-step mitigation and hardening guidance for CVE-2026-58165 — configuration checks, workarounds where no patch exists, and how to verify you're protected — is on the way.

10 · FAQ

FAQ: CVE-2026-58165

How does the CVE-2026-58165 privilege escalation work?

A non-admin identity that has been granted the enrollment permission creates a new one-time-token enrollment for the default admin identity via the management API, then redeems that enrollment through the unauthenticated client /enroll endpoint to obtain a client certificate that authenticates as the admin identity -- yielding full administrative control over the controller and its zero-trust overlay.

How severe is CVE-2026-58165?

High severity -- it lets a low-privileged, non-admin authenticated identity escalate to full administrative compromise of the OpenZiti controller, bypassing role-based access controls.

How can I reproduce CVE-2026-58165?

Download the verified script from this page and run it in an isolated environment against an OpenZiti controller through version 2.0.0. It creates a low-privileged identity with enrollment-management permission, uses it to create an enrollment for the built-in admin identity, redeems that enrollment via the client /enroll endpoint, and confirms the resulting certificate authenticates with admin privileges.
11 · References

References for CVE-2026-58165

Authoritative sources for CVE-2026-58165 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.