CVE-2026-16450 Overview
CVE-2026-16450 is an authorization bypass vulnerability in the zsadmin2025 ZS-Admin application up to commit b52e14536d59fda11e56e2536a1c32e82a38cead. The flaw resides in the getTenantId function of the /api/system/sys/dept/page endpoint within the MyBatis-Plus Tenant Plugin component. Attackers can manipulate the X-Tenant-Id HTTP header to bypass tenant isolation controls and access data belonging to other tenants. The vulnerability is exploitable remotely by authenticated users with low privileges. ZS-Admin uses a rolling release model, so no fixed version identifier has been published, and the maintainers have not responded to the initial issue report.
Critical Impact
Authenticated remote attackers can bypass tenant isolation in the MyBatis-Plus Tenant Plugin by manipulating the X-Tenant-Id header, exposing data across tenant boundaries.
Affected Products
- zsadmin2025 ZS-Admin up to commit b52e14536d59fda11e56e2536a1c32e82a38cead
- MyBatis-Plus Tenant Plugin as integrated in ZS-Admin
- Rolling release deployments of zs-admin-java
Discovery Timeline
- 2026-07-21 - CVE-2026-16450 published to NVD
- 2026-07-23 - Last updated in NVD database
Technical Details for CVE-2026-16450
Vulnerability Analysis
The vulnerability is classified as Improper Authorization [CWE-285]. ZS-Admin implements multi-tenant data segregation through the MyBatis-Plus Tenant Plugin, which appends a tenant filter to SQL queries based on the resolved tenant identifier. The getTenantId function inside the plugin retrieves the tenant context from the X-Tenant-Id request header without verifying that the caller is authorized to operate under the supplied tenant. When a user sends a request to /api/system/sys/dept/page, the plugin trusts the client-supplied header and injects it directly into the tenant predicate. This allows any authenticated user to enumerate departmental data belonging to arbitrary tenants by rotating the header value. The EPSS score is 0.358% with a percentile of 28.3, and a public exploit reference has been recorded in VulDB.
Root Cause
The root cause is missing authorization enforcement between the authenticated session and the tenant context supplied through the X-Tenant-Id header. The getTenantId implementation treats the header as authoritative rather than validating it against the user's assigned tenant claims. No server-side mapping between the authenticated principal and the requested tenant is performed before query execution.
Attack Vector
An attacker authenticates with any low-privilege account, then issues a request to /api/system/sys/dept/page and substitutes the X-Tenant-Id header with the identifier of a target tenant. The MyBatis-Plus Tenant Plugin rewrites the SQL predicate using the attacker-controlled value, returning department records from the victim tenant. No user interaction is required. Because the exploit primitive is a single HTTP header modification, it is trivial to automate across tenant identifiers.
No verified proof-of-concept code has been published in a public exploit repository beyond references to the GitHub Issue Discussion and VulDB CVE-2026-16450. Refer to those sources for technical details.
Detection Methods for CVE-2026-16450
Indicators of Compromise
- HTTP requests to /api/system/sys/dept/page containing an X-Tenant-Id header whose value does not match the authenticated user's assigned tenant.
- Repeated requests from the same session iterating through sequential or enumerated X-Tenant-Id values.
- Application logs showing tenant context switches within a single authenticated session.
Detection Strategies
- Instrument the authentication layer to log both the session-bound tenant and the header-supplied tenant, then alert on mismatches.
- Deploy Web Application Firewall (WAF) rules that inspect the X-Tenant-Id header for values outside the authenticated user's authorized scope.
- Correlate access to /api/system/sys/dept/* endpoints with the session's tenant claim to identify cross-tenant enumeration.
Monitoring Recommendations
- Baseline normal tenant access patterns per user and alert on deviations exceeding the baseline within short time windows.
- Enable verbose audit logging for MyBatis-Plus Tenant Plugin decisions and forward logs to a centralized SIEM.
- Monitor volumetric spikes on /api/system/sys/dept/page from a single authenticated principal.
How to Mitigate CVE-2026-16450
Immediate Actions Required
- Reject requests where the X-Tenant-Id header does not match the tenant identifier bound to the authenticated session.
- Restrict network exposure of the /api/system/sys/* API surface to trusted administrative networks until a fix is available.
- Review audit logs for prior cross-tenant access attempts and notify affected tenants if evidence is found.
Patch Information
No vendor patch has been released. The project uses a rolling release model, and the maintainers have not responded to the GitHub Issue Discussion. Operators should track the upstream repository and apply the fix as soon as a corrective commit is merged. Additional context is available in the VulDB Vulnerability #380829 entry.
Workarounds
- Override getTenantId in the MyBatis-Plus Tenant Plugin to derive the tenant identifier from the authenticated principal's claims instead of the HTTP header.
- Add a request filter that strips or validates the X-Tenant-Id header against the session tenant before controllers execute.
- Enforce role-based access control at the API gateway to block cross-tenant identifiers per authenticated user.
# Example Spring interceptor logic to validate tenant header against session
# Reject requests when the header-supplied tenant differs from the session tenant
if [ "$X_TENANT_ID_HEADER" != "$SESSION_TENANT_ID" ]; then
return 403
fi
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

