Dead `usr` query parameter passed to sqleditor.connect_server never reaches the backend
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- flask, javascript, python
- Domain
- api, full-stack
Research direction
Start with the three listed call sites—connectServer.js, AdHocConnection.jsx, and NewConnectionDialog.jsx—and compare them with static/js/url_for.js and the sqleditor.connect_server route. Reproduce the generated URL with a usr value, then confirm the selected outcome consistently removes the dead argument or wires it through the route and handler.
Written by the indexing model from the issue text.
Description
Please note that security bugs or issues should be reported to security@pgadmin.org.
(Not applicable here — this is not a security issue.)
Describe the bug
Three frontend call sites build the URL for sqleditor.connect_server with an extra
usr value, apparently intending to tell the backend which database user a password
retry is for:
web/pgadmin/tools/sqleditor/static/js/components/connectServer.js:40web/pgadmin/misc/workspaces/static/js/AdHocConnection.jsx:362web/pgadmin/tools/sqleditor/static/js/components/dialogs/NewConnectionDialog.jsx:235
All three call url_for('sqleditor.connect_server', {'sid': sid, ...(user ? {'usr': user} : {})}).
url_for() (web/pgadmin/static/js/url_for.js) only substitutes <...> placeholders that
appear in the Flask route template:
module.exports = function(endpoint, substitutions) {
let rawURL = endpoints[endpoint];
let substitutionGroupsRegExp = /(<)([^:^>]*:)?([^>]+)(>)/g,
interpolated = rawURL;
if (!rawURL) return rawURL;
interpolated = interpolated.replace(substitutionGroupsRegExp, function(_origin, _1, _2, substitutionName) {
if (substitutionName in substitutions) {
return substitutions[substitutionName];
}
return _origin;
});
return interpolated;
};
Any key in substitutions that doesn't match a <placeholder> in the route template is
silently dropped — it is never appended as a query string, unlike Flask's own server-side
url_for(), which appends unmatched kwargs as ?key=value. The Flask route itself is:
@blueprint.route('/connect_server/<int:sid>', methods=["POST"], endpoint="connect_server")
— only <int:sid> is a placeholder, so usr is discarded before the request is even sent.
The backend's connect_server(sid) handler never reads a usr parameter either way.
To Reproduce
- In any of the three flows above (password re-prompt in the Query Tool, the ad-hoc
Workspace "Existing Server" dialog, or the in-tool "New Connection" dialog), trigger a
call toconnectServer(...)with auserargument set. - Inspect the actual outgoing request (e.g. browser DevTools Network tab, or add a
console.log(url_for('sqleditor.connect_server', {sid, usr: 'someuser'}))).
Expected behavior
Either:
- the constructed URL includes the intended user information (e.g. as a real query
string parameter, with matching support added tourl_for()and read server-side), or - the dead
usrkey is removed from all three call sites, since it currently does
nothing and reads as though the backend is user-aware when it is not.
Error message
No error is raised — this is silent dead code, not a crash. console.log(url_for('sqleditor.connect_server', {sid: 6, usr: 'test'})) returns /sqleditor/connect_server/6 with no trace of usr.
Screenshots
N/A — not a visual bug.
Desktop (please complete the following information):
- OS: N/A (code-level issue, reproducible on any platform)
- pgAdmin version: confirmed present on
master(commit 81edb68b, 2026-09-14) - Mode: Desktop and Server (affects both — the code path is shared)
- Browser (if running in server mode): N/A
- Package type: N/A
Additional context
Found while investigating an authentication bug in a downstream product built on
pgAdmin (Postgres Enterprise Manager / PEM-6245), where a fix initially assumed this
usr parameter reached the backend and could be used to route a password retry to the
correct database role. It doesn't, in either codebase — the actual fix there had to use
a different mechanism. Filing here since the same dead parameter exists unmodified in
pgAdmin itself. Low severity: it doesn't currently cause any incorrect behavior in
pgAdmin's own flows (upstream's ad-hoc connections clone the server per-role, so the
retry path works without needing usr), but the parameter is misleading dead code that
should either be wired up or removed.
- Dominant language
- Python
- Stars
- 3.8k
- Forks
- 891
- Avg merge
- 3d 10h
- Merged PRs (30d)
- 10
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from pgadmin-org/pgadmin4
-
Feature
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
pgadmin-org/pgadmin4#10426 · 1 comment ·
-
Bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
pgadmin-org/pgadmin4#10424 ·
-
Bug
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
pgadmin-org/pgadmin4#10408 · 2 comments ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
pgadmin-org/pgadmin4#10401 ·
-
Bug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
pgadmin-org/pgadmin4#10361 ·
All issues in pgadmin-org/pgadmin4
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100