Skip to content

CVE-2026-58377: Verified Reproduction

CVE-2026-58377: JeecgBoot broken access control privilege escalation

CVE-2026-58377 is verified against jeecgboot/JeecgBoot · github. Affected versions: JeecgBoot through 3.9.2 (all versions up to and including 3.9.2). Vulnerability class: Privilege Escalation. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00250.

REPRO-2026-00250 jeecgboot/JeecgBoot · github Privilege Escalation Jul 6, 2026 CVE entry .txt
Severity
HIGH
CVSS
8.1
Confidence
HIGH
Reproduced in
31m 46s
Tool calls
271
Spend
$4.34
01 · Overview

What Is CVE-2026-58377?

CVE-2026-58377 is a high-severity broken access control vulnerability in JeecgBoot that lets an authenticated low-privileged user escalate privileges. Pruva reproduced it (reproduction REPRO-2026-00250).

02 · Severity & CVSS

CVE-2026-58377 Severity & CVSS Score

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

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

High — serious impact or readily exploitable. Prioritize remediation.

03 · Affected Versions

Affected jeecgboot/JeecgBoot Versions

jeecgboot/JeecgBoot · github versions JeecgBoot through 3.9.2 (all versions up to and including 3.9.2) are affected.

How to Reproduce CVE-2026-58377

$ pruva-verify REPRO-2026-00250
or curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00250/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-58377

Authorization bypass — 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

authenticated low-privileged user JWT token (ceshi/test role, password 123456)

Attack chain
  1. POST /jeecg-boot/sys/login (ceshi)
  2. GET/POST/DELETE /jeecg-boot/openapi/auth/* with X-Access-Token header
How the agent worked 629 events · 271 tool calls · 32 min
32 minDuration
271Tool calls
172Reasoning steps
629Events
1Dead-ends
Agent activity over 32 min
Support
22
Repro
390
Judge
28
Variant
185
0:0031:46

Root Cause and Exploit Chain for CVE-2026-58377

Versions: JeecgBoot through 3.9.2 (commit 7df07a823fd558be857d0208ccae96342539fbc1, tag v3.9.2)

JeecgBoot v3.9.2 contains a broken access control vulnerability in the OpenAPI credential management module. The OpenApiAuthController (/openapi/auth/*) and OpenApiPermissionController (/openapi/permission/*) expose full CRUD endpoints for managing OpenAPI AK/SK credential pairs without any Shiro authorization annotations (@RequiresRoles or @RequiresPermissions). In contrast, the sibling OpenApiController (/openapi/*) correctly annotates its mutating endpoints with @RequiresRoles({"admin"}). Because the Shiro filter chain maps /** to the jwt filter (authentication-only, no authorization), any authenticated user — including low-privileged users with only a "test" role — can list, create, edit, and delete all OpenAPI credential pairs, with the list endpoint returning secret keys (SK) in plaintext. This enables credential theft and unauthorized invocation of the OpenAPI surface, including endpoints owned by administrator accounts.

  • Package/component affected: jeecg-boot/jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/openapi/controller/OpenApiAuthController.java and OpenApiPermissionController.java
  • Affected versions: JeecgBoot through 3.9.2 (commit 7df07a823fd558be857d0208ccae96342539fbc1, tag v3.9.2)
  • Risk level: HIGH (CVSS 4.0: 8.6)
  • Consequences:
    • Any authenticated low-privilege user can read all OpenAPI AK/SK credential pairs in plaintext, including those belonging to administrators.
    • Low-privilege users can create, modify, and delete credential records without administrative authorization.
    • Stolen credentials can be used to invoke the OpenAPI surface (/openapi/call/**, which is mapped to anon and only checks the appkey header), impersonating the credential owner — including administrators.

Impact Parity

  • Disclosed/claimed maximum impact: Privilege escalation — authenticated low-privilege users perform full CRUD on OpenAPI credentials, read admin secret keys in plaintext, and can invoke privileged API routes as the credential owner.
  • Reproduced impact from this run: A low-privileged user (ceshi, role=test) successfully:
    1. Read admin's AK/SK credentials in plaintext via GET /openapi/auth/list (ak=ak-pFjyNHWRsJEFWlu6, sk=4hV5dBrZtmGAtPdbA5yseaeKRYNpzGsS, owner=admin)
    2. Created a new OpenAPI credential via POST /openapi/auth/add (persisted to database)
    3. Deleted an OpenAPI credential via DELETE /openapi/auth/delete
    4. Generated a new AK/SK pair via GET /openapi/auth/genAKSK
    5. Was correctly rejected by the protected POST /openapi/add endpoint (has @RequiresRoles({"admin"})), confirming the authorization gap is specific to OpenApiAuthController
  • Parity: full — all claimed CRUD operations on OpenAPI credentials were demonstrated, including plaintext secret key exposure and the negative control showing the sibling controller is properly protected.
  • Not demonstrated: Actual invocation of /openapi/call/** with stolen credentials to impersonate the admin (the second root cause described in the advisory). The primary broken access control on credential management endpoints is fully proven.

Root Cause

The Shiro security configuration (ShiroConfig.java) maps all URL paths (/**) to the jwt filter, which performs authentication only (validates JWT token existence and signature). Authorization (role/permission checks) is enforced exclusively through method-level annotations such as @RequiresRoles and @RequiresPermissions.

The OpenApiAuthController at /openapi/auth/* exposes seven endpoints — GET /list, POST /add, PUT /edit, DELETE /delete, DELETE /deleteBatch, GET /queryById, and GET /genAKSK — none of which carry any Shiro authorization annotation. This means the Shiro authorization layer is never triggered for these endpoints; any user who passes JWT authentication can access them.

In contrast, the sibling OpenApiController at /openapi/* correctly annotates its mutating endpoints (/add, /edit, /delete, /deleteBatch) with @RequiresRoles({"admin"}), which triggers Shiro's AuthorizationAttributeSourceAdvisor and enforces that only users with the "admin" role can perform those operations.

The OpenApiPermissionController at /openapi/permission/* has the same absence of authorization annotations on its POST /add and GET /getOpenApi endpoints.

Additionally, the /openapi/call/** path is mapped to anon (no authentication required at all), and the OpenApiController.call() method only reads the appkey header to look up the auth record without verifying the secret key signature, enabling unauthorized API invocation with stolen credentials.

Fix commit: Not yet publicly available in the main branch as of this analysis. The fix would involve adding @RequiresRoles({"admin"}) annotations to all mutating endpoints in OpenApiAuthController and OpenApiPermissionController, and implementing SK signature verification in the call() method.

Reproduction Steps

  1. Reference: bundle/repro/reproduction_steps.sh
  2. What the script does:
    • Resolves the JeecgBoot v3.9.2 repository from the prepared project cache
    • Installs JDK 17, Maven, Redis, and MariaDB if not present
    • Starts MariaDB and Redis, creates the jeecg-boot database, and imports the seed SQL (which includes an admin-owned OpenAPI credential)
    • Uses the pre-built jeecg-system-start-3.9.2.jar (or builds it with Maven if not present)
    • Starts the JeecgBoot Spring Boot application with login captcha disabled (--jeecg.firewall.enableLoginCaptcha=false)
    • Logs in as the low-privileged user ceshi (role: test, password: 123456) and obtains a JWT token
    • Calls GET /openapi/auth/list with the low-priv JWT to read all AK/SK credentials in plaintext
    • Calls POST /openapi/auth/add to create a credential as the low-priv user (verified in database)
    • Calls DELETE /openapi/auth/delete to delete a credential as the low-priv user
    • Calls GET /openapi/auth/genAKSK to generate an AK/SK pair as the low-priv user
    • Negative control: Calls POST /openapi/add (which has @RequiresRoles({"admin"})) and confirms it rejects the low-priv user with "Subject does not have role [admin]"
    • Admin positive control: Logs in as admin and confirms admin can access POST /openapi/add
    • Writes the runtime manifest with all proof artifacts
  3. Expected evidence of reproduction:
    • artifacts/http/openapi_auth_list_response.json — shows success: true with admin's AK/SK in plaintext
    • artifacts/http/openapi_auth_add_response.json — shows success: true (low-priv user created credential)
    • artifacts/http/openapi_auth_delete_response.json — shows success: true (low-priv user deleted credential)
    • artifacts/http/openapi_auth_genAKSK_response.json — shows success: true with generated AK/SK pair
    • artifacts/http/openapi_add_negcontrol_response.json — shows success: false with "Subject does not have role [admin]"
    • artifacts/http/openapi_add_admin_response.json — shows success: true (admin can access protected endpoint)

Evidence

  • Log file locations:

    • bundle/logs/reproduction_steps.log — full script execution log
    • bundle/logs/jeecgboot_app.log — JeecgBoot application startup and runtime log
    • bundle/artifacts/http/*.json — HTTP request/response captures for each proof
  • Key excerpts proving reproduction:

    PROOF 1 — Low-priv user reads admin's AK/SK in plaintext (openapi_auth_list_response.json):

    {
      "success": true,
      "code": 200,
      "result": {
        "records": [{
          "id": "1922164194775056386",
          "name": "scott",
          "ak": "ak-pFjyNHWRsJEFWlu6",
          "sk": "4hV5dBrZtmGAtPdbA5yseaeKRYNpzGsS",
          "systemUserId": "e9ca23d68d884d4ebb19d07889727dae",
          "systemUserId_dictText": "admin"
        }]
      }
    }
    

    NEGATIVE CONTROL — Protected endpoint rejects low-priv user (openapi_add_negcontrol_response.json):

    {
      "success": false,
      "message": "Subject does not have role [admin]",
      "code": 500
    }
    
  • Environment details:

    • JeecgBoot v3.9.2 (Spring Boot 3.5.5, Java 17.0.19)
    • MariaDB 11.8.6, Redis 8.0.5
    • Low-priv user: ceshi (role: test, tenant: 1001)
    • Admin user: admin (role: admin, tenant: 1000)
    • Application context path: /jeecg-boot, port 8080

Recommendations / Next Steps

  • Fix approach: Add @RequiresRoles({"admin"}) annotations to all mutating endpoints in OpenApiAuthController (/add, /edit, /delete, /deleteBatch) and OpenApiPermissionController (/add). Consider whether the /list, /queryById, and /genAKSK endpoints should also be admin-only or restricted to credentials owned by the requesting user.
  • Additional fix: Implement secret key (SK) signature verification in OpenApiController.call() to prevent unauthorized API invocation with stolen AK-only credentials.
  • Upgrade guidance: Upgrade to a version that includes the fix once available. In the interim, restrict access to /openapi/auth/** and /openapi/permission/** via reverse proxy rules (e.g., nginx) to admin-only users.
  • Testing recommendations: Add integration tests that verify non-admin users receive 403/510 responses when accessing OpenAPI credential management endpoints. Add tests that verify SK signature validation in the call endpoint.

Additional Notes

  • Idempotency confirmation: The script was run twice consecutively, both runs succeeded with exit code 0 and all 4 proofs confirmed. The script drops and recreates the database on each run, ensuring a clean state.
  • Captcha handling: Login captcha was disabled via --jeecg.firewall.enableLoginCaptcha=false Spring Boot argument to enable automated login. This does not affect the vulnerability — the captcha is an authentication-layer control, while the vulnerability is in the authorization layer.
  • Port conflict: Apache2 was found occupying port 8080 in the test environment; the script kills it before starting JeecgBoot.
  • Seed data: The seed SQL includes one admin-owned OpenAPI credential (name: scott, ak: ak-pFjyNHWRsJEFWlu6, sk: 4hV5dBrZtmGAtPdbA5yseaeKRYNpzGsS, systemUserId: admin), which serves as the target credential for the privilege escalation proof.

CVE-2026-58377 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:000:50
0:00
session startedaccounts/fireworks/routers/glm-5p2-fast · CVE-2026-58377 · REPRO-20
0:02
0:04
web search
0:05
web search
0:07
0:17
web search
0:19
web search
0:21
0:24
0:26
web search
0:28
0:30
web search
0:31
web search
0:43
0:43
extract_facts
no facts extracted
0:44
0:44
0:44
supportrepro
0:45
0:45
0:45
0:45
0:46
0:46
0:46
0:49
0:49
0:49
0:50
0:50
08 · How to Fix

How to Fix CVE-2026-58377

Coming soon

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

10 · FAQ

FAQ: CVE-2026-58377

How does the JeecgBoot privilege escalation work?

Because the Shiro filter chain maps /** to the authentication-only jwt filter, any authenticated user - including a low-privileged user with only a "test" role - can list, create, edit, and delete all OpenAPI credential pairs, and the list endpoint returns the plaintext secret keys (SK), enabling credential theft and unauthorized invocation of the OpenAPI surface owned by administrator accounts.

Which JeecgBoot versions are affected by CVE-2026-58377?

JeecgBoot through 3.9.2 (all versions up to and including 3.9.2) are affected, verified at commit 7df07a823fd558be857d0208ccae96342539fbc1 / tag v3.9.2.

How severe is CVE-2026-58377?

It is rated high severity (CVSS 4.0: 8.6 per the root-cause analysis) - any authenticated low-privilege user can read all OpenAPI AK/SK credential pairs in plaintext, including administrators', and reuse them.

How can I reproduce CVE-2026-58377?

Download the verified script from this page and run it in an isolated environment against JeecgBoot <=3.9.2; create a low-privileged user and send requests to the unguarded OpenApiAuthController/OpenApiPermissionController endpoints to list and manage admin-owned OpenAPI credentials.
11 · References

References for CVE-2026-58377

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