The pgAdmin Development Team is pleased to announce the release of pgAdmin 4 version 9.18. This release of pgAdmin 4 includes 29 bug fixes and new features, including fixes for four security vulnerabilities (CVE-2026-86861 through CVE-2026-86864). For more details, please see the release notes.
pgAdmin is the leading open-source graphical management tool for PostgreSQL. For more information, please see the website.
Notable changes in this release include:
Ctrl+Alt+B by default, does the same thing and can be changed through the new toggle_object_explorer preference.'unsafe-inline', and drop 'unsafe-eval'. style-src keeps 'unsafe-inline', because MUI and React inject runtime styles and inline style attributes that cannot carry a nonce, and development bundles have 'unsafe-eval' re-added automatically when DEBUG is set.get_user() fell back to reading the configured WEBSERVER_REMOTE_USER name from the inbound request headers when it was absent from the WSGI environment. Because a header is written by whoever sends the request, any client that could reach pgAdmin could assert any identity, including an administrator's, without presenting a credential. A header-asserted identity is now opt-in, restricted to a configured list of trusted proxies with an optional shared secret, and refused for accounts whose authentication source is not webserver (CVE-2026-86863).pg_dump argument vector as a bare positional value. Because getopt_long permutes arguments, a value beginning with a dash supplied further options such as --file, overriding the storage-confined output path; and because libpq expands a database name containing an equals sign into a full connection string, the same field could redirect the connection, and the password exported in PGPASSWORD, to a host of the caller's choosing. The database name is now passed through the PGDATABASE environment variable, which libpq never expands (CVE-2026-86864).--dbname and could likewise redirect the connection, and the exported password, to a server of the caller's choosing (CVE-2026-86862).save_file endpoint, which backs saving from the Query Tool and ERD: the requested path was validated with check_access_permission() and then opened with a plain open(), so a symbolic link planted in between was followed, writing outside the user's storage directory. This is the write sink that CVE-2026-7819's hardening of the separate upload path did not cover (CVE-2026-86861).Location header on to a destination the ALLOWED_LLM_API_URLS check was never applied to. This is hardening rather than a fix for an exploitable flaw, since returning the redirect at all requires control of a host already on the allowlist.Username when importing a non-shared server, which previously imported cleanly and left a server that libpq would silently authenticate as the OS account running pgAdmin rather than reject outright.UserMixin.is_locked() that pgAdmin's own is_locked() had been written against.dependLevel unset.getNodeAjaxOptions() so a wide table's Columns tab no longer fires one duplicate get_types request per column row.TABLESPACE pg_default clause from generated index SQL, which was invalid on a partitioned table.pg_service.conf) connection, which leaves host, port and username unset.SharedUsername when importing a shared server from a servers.json definition, instead of insisting on Username for every server.ProductVersion, and fix the existingSecret path in the Helm deployment template.SERVER_MODE is set, leaving desktop mode with internal authentication alone.Builds for Windows and macOS are available now, along with a Python Wheel, Docker Container, RPM, DEB Package, and source code tarball from the download area.