The file mixed issue-backed entries with commit-id ones. Make every
entry issue-backed:
- The LLM API redirect hardening had no issue, and its entry was the
only record of Ziya Abdullayev's report outside the commit message.
It gets #10420, written up with the mechanism, the affected range
(>= 9.15, since ALLOWED_LLM_API_URLS did not exist before then) and
the fix commit, and noting that it is hardening rather than an
exploitable flaw, so no CVE was requested.
- The Table dialog fix closed two issues, #10179 and #10180, so it
becomes two entries. That also covers the Definition-tab type
restriction, which the single commit-id entry had omitted.
- The remaining commit-id entries are dropped.
12 KiB
12 KiB
Version 9.18
Release date: 2026-09-17
This release contains a number of bug fixes and new features since the release of pgAdmin 4 v9.17.
Supported Database Servers
PostgreSQL: 14, 15, 16, 17 and 18
EDB Advanced Server: 14, 15, 16, 17 and 18
Bundled PostgreSQL Utilities
psql, pg_dump, pg_dumpall, pg_restore: 18.4
New features
Issue #9631 - Collapse and restore the Object Explorer by re-clicking the current workspace icon, in the manner of the VS Code side bar, remembering the choice across refreshes. A keyboard shortcut, Ctrl+Alt+B by default, does the same thing and can be changed through the newtoggle_object_explorerpreference.
Housekeeping
Issue #10221 - Skip importing and initialising the kerberos, ldap, mfa, oauth2 and webserver authentication providers unlessSERVER_MODEis set, leaving desktop mode with internal authentication alone.
Issue #10247 - Relax theazure-mgmt-resourcepin to allow 24.0.0, and aggregate the third-party JavaScript and Python dependency bumps for this release.
Issue #10293 - Make the Schema Diff regression test assert its own generated script, which it previously swallowed, so invalid generated SQL can no longer pass silently.
Bug fixes
Issue #9226 - AcceptSharedUsernamewhen importing a shared server from a servers.json definition, instead of insisting onUsernamefor every server.
Issue #10155 - Share concurrent identical GET requests behindgetNodeAjaxOptions()so a wide table's Columns tab no longer fires one duplicateget_typesrequest per column row.
Issue #10179 - Fix inherited columns in the Table dialog being editable and deletable: a column already inherited from a parent carriesinheritedfromtablewhile one fetched interactively through 'Inherited from table(s)' carriesinheritedfromand has noattnumyet, and only the latter was checked, after anisNew()short-circuit that treated the attnum-less rows as new.
Issue #10180 - Fix the Data type dropdown on the expanded Definition tab of the Table dialog offering every type, ignoring the allowed-type restriction already applied to the inline editor.
Issue #10214 - Fix theexistingSecretpath in the Helm deployment template.
Issue #10235 - Remove a trailing quote from the Windows installer'sProductVersion, which was stamped as e.g.9.17".
Issue #10236 - Fix Schema Diff reporting false differences for SERIAL/BIGSERIAL columns by ignoring the owned sequence's oid, and fix the invalidALTER COLUMN ... TYPE bigserialSQL generated when such a column genuinely differs.
Issue #10237 - Fix areplace() argument 2 must be str, not Nonecrash when a per-server Password Exec Command is used with a service-only (pg_service.conf) connection, which leaves host, port and username unset.
Issue #10239 - Remove a redundantpasslibpin that conflicts with the indirectly requiredlibpass.
Issue #10252 - Fix the argument grid on the Definition tab of a user-defined function or procedure refusing to delete, or add, a row in edit mode.
Issue #10295 - Reinstate dependency ordering of the script Schema Diff generates, which had been lost since the React port leftdependLevelunset.
Issue #10297 - Fix Schema Diff duplicating any column that also differs when it recreates a foreign table.
Issue #10298 - Fix Schema Diff generating SQL that PostgreSQL rejects when a sequence's MINVALUE is raised above its current value.
Issue #10300 - Fix a foreign table column added by Schema Diff losing its collation.
Issue #10302 - Fix Schema Diff injecting whitespace into an applied function or procedure body, which left a whitespace-only difference behind.
Issue #10303 - Report a Schema Diff comparison that fails part way through as a failure, rather than as a success.
Issue #10309 - Reject an empty or nullUsernamewhen importing a non-shared server, which previously imported cleanly and left a server libpq would silently authenticate as the OS account running pgAdmin.
Issue #10311 - Fix login being impossible against Flask-Security-Too 5.8.2, which corrected a long-standing inversion inUserMixin.is_locked()thatUser.is_locked()had been written against.
Issue #10341 - Omit the redundantTABLESPACE pg_defaultclause from generated index SQL, which was invalid on a partitioned table.
Issue #10383 - Fix an authentication bypass in Webserver authentication mode, whereget_user()fell back to reading the configuredWEBSERVER_REMOTE_USERname from the request headers when it was absent from the WSGI environment, letting any client that could reach pgAdmin assert any identity, including an administrator's (CVE-2026-86863). 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 notwebserver. Reported by Sanghyeon Lee (@h9e0n).
Issue #10384 - Fix argument and connection-string injection in the Backup tool, where the client-supplied database name was appended to the pg_dump argument vector as a bare positional argument: 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, one could also redirect the connection to an attacker-controlled host and exfiltrate the stored password (CVE-2026-86864). The database name is now passed through thePGDATABASEenvironment variable instead. Reported by Sanghyeon Lee (@h9e0n) and Hitesh Jambhale.
Issue #10385 - Fix a time-of-check to time-of-use flaw in the File Manager'ssave_fileendpoint, which backs saving from the Query Tool and ERD: the requested path was validated withcheck_access_permission()and then opened with a plainopen(), so a symbolic link planted in between was followed, writing outside the storage directory. This is the sink CVE-2026-7819's hardening of the separate upload path did not cover (CVE-2026-86861). Reported by sec-rex.
Issue #10388 - Fix connection-string injection in the Restore and Maintenance tools, where the client-supplied database name was passed straight to--dbname: libpq expands a database name containing an equals sign into a full connection string, whose embedded keywords override the--hostand--portpgAdmin supplies, so the connection - and the stored password exported inPGPASSWORD- could be redirected to a server of the caller's choosing (CVE-2026-86862). The database name is now passed through thePGDATABASEenvironment variable, which libpq never expands. Found by Hitesh Jambhale.
Issue #10393 - Render the Validate binary path dialog as HTML, instead of showing the raw markup.
Issue #10420 - Refuse HTTP redirects on LLM API requests, rather than following aLocationheader on to a destinationALLOWED_LLM_API_URLSwas 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. Reported by Ziya Abdullayev.
Dependencies
Non-breaking dependabot and audit-driven bumps
aggregated for v9.18.
Python:
Authlib1.7.* -> 1.8.*
azure-mgmt-resource==25.0.0 -> >=24.0.0,<26.0.0
certifi2026.6.17 -> 2026.7.22
cryptography49.0.* -> 50.0.*
Flask-Security-Too5.8.* -> >=5.8.2,<5.9
google-auth-oauthlib1.4.0 -> 1.4.1
gssapi1.11.* -> 1.12.*
passlib1.* pin removed (redundant, and conflicting withlibpass)
psycopg[c]3.3.4 -> 3.3.5
selenium(web/regression) 4.45.0 -> 4.48.0
setuptools83.* -> 84.*
testscenarios(web/regression) 0.6.2 -> 0.7.0
typer0.26.* -> 0.27.*
Skipped:paramiko3 -> 5 (blocked onsshtunnel'sparamiko.DSSKeyusage) andazure-mgmt-resource26.0.0 (drops Python 3.9 support)
JavaScript (web/):
@babel/*toolchain (core, eslint-parser, eslint-plugin, plugin-syntax-jsx, plugin-transform-class-properties, plugin-transform-object-rest-spread, plugin-transform-runtime, preset-env, preset-react, preset-typescript) -> 7.29.7
@mui/icons-material/@mui/material7.3.10 -> 7.3.11
@mui/x-date-pickers8.28.3 -> 8.29.3
@tanstack/react-query5.101.4 -> 5.102.8
@tanstack/react-virtual3.13.24 -> 3.14.10
@testing-library/jest-dom6.9.1 -> 6.10.0
@testing-library/react16.3.2 -> 16.3.3
@testing-library/user-event14.6.1 -> 14.6.3
@types/react19.2.17 -> 19.2.18
@types/react-dom19.2.3 -> 19.2.5
anti-trojan-source1.12.0 -> 1.12.2
axios1.18.1 -> 1.20.0
codemirror6.0.2 -> 6.65.7
core-js3.49.0 -> 3.50.0
css-loader7.1.4 -> 7.1.5
diff-arrays-of-objects1.1.10 -> 1.1.11
dompurify3.4.12 -> 3.4.14
eslint9.39.4 -> 9.39.5
eslint-plugin-jest29.15.5 -> 29.16.6
globals17.7.0 -> 17.12.0
hotkeys-js4.0.4 -> 4.0.7
image-minimizer-webpack-plugin4.1.4 -> 5.0.0
ip-address10.2.0 -> 10.7.0
jest/jest-environment-jsdom30.4.2 / 30.4.1 -> 30.5.1
lossless-json4.3.0 -> 4.3.1
marked18.0.7 -> 18.0.11
papaparse5.5.4 -> 5.7.0
postcss8.5.20 -> 8.5.26
rc-dock4.0.0-alpha.2 -> 4.0.0-alpha.3
react/react-dom19.2.7 -> 19.2.8
react-arborist3.5.0 -> 3.16.0
react-draggable4.7.0 -> 4.7.1
sharp0.35.3 -> 0.35.4
svgo4.0.2 -> 4.1.0
svgo-loader4.0.0 -> 5.0.0
typescript-eslint8.65.0 -> 8.69.0
use-resize-observer9.1.0 -> 10.0.0
vanilla-jsoneditor3.12.0 -> 3.13.0
webpack-bundle-analyzer5.3.1 -> 5.3.2
zustand5.0.14 -> 5.0.15
Transitive advisory bumps:brace-expansion,fast-uri,js-yaml,shell-quote,socket.io-parser,tar
Held back:@simonwep/pickr1.10.x (webpack production-bundle interop break), Babel 8, andwebpack5.110.3 (npm-quarantined at bump time)
JavaScript (runtime/):
axios1.18.1 -> 1.19.0
electron43.1.1 -> 43.4.0
eslint10.7.0 -> 10.8.1
globals17.7.0 -> 17.11.0
ip-address10.2.0 -> 10.3.1
postcss8.5.20 -> 8.5.23
Transitive advisory bumps:brace-expansion,fast-uri,undici