CVE-2026-7820

Source
https://cve.org/CVERecord?id=CVE-2026-7820
Import Source
https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-7820.json
JSON Data
https://api.osv.dev/v1/vulns/CVE-2026-7820
Aliases
Related
Published
2026-05-11T14:35:53.492Z
Modified
2026-07-15T01:49:19.316433052Z
Severity
  • 6.9 (Medium) CVSS_V4 - CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:N/SC:N/SI:N/SA:N CVSS Calculator
Summary
pgAdmin 4: Account-lockout bypass via Flask-Security default /login view
Details

Improper restriction of excessive authentication attempts (CWE-307) in pgAdmin 4.

pgAdmin enforces MAXLOGINATTEMPTS only inside its custom /authenticate/login view. Flask-Security's default /login view, which is registered automatically by security.initapp() and is reachable on every server, never consulted the User.locked field: pgAdmin's User model relied on Flask-Security's UserMixin.islocked() (which always returns 'not locked') and Flask-Login's isactive (which only checks the active column, not locked). An attacker who triggered an account lockout via /authenticate/login could therefore obtain a session by re-submitting valid credentials directly to /login, defeating the brute-force-protection control for accounts using the INTERNAL authentication source. The same bypass also means that login attempts via /login are never rate-limited, so an attacker can perform an unbounded online password-guessing attack against INTERNAL accounts regardless of MAXLOGIN_ATTEMPTS.

Fix overrides User.isactive and User.islocked() so the locked column is enforced on every authentication path. LDAP, OAuth2, Kerberos, and Webserver users are not reachable by this bypass because they have no local password and are rejected by Flask-Security's LoginForm.validate before the locked check; the lockout itself is also internal-only (the /authenticate/login view filters by auth_source=INTERNAL).

This issue affects pgAdmin 4: before 9.15.

Database specific
{
    "cna_assigner": "PostgreSQL",
    "osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/7xxx/CVE-2026-7820.json"
}
References

Affected packages

Git / github.com/pgadmin-org/pgadmin4

Affected ranges

Type
GIT
Repo
https://github.com/pgadmin-org/pgadmin4
Events
Introduced
0 Unknown introduced commit / All previous commits are affected
Fixed
Database specific
{
    "source": [
        "AFFECTED_FIELD",
        "CPE_RANGE"
    ],
    "cpe": "cpe:2.3:a:pgadmin:pgadmin_4:*:*:*:*:*:postgresql:*:*",
    "extracted_events": [
        {
            "introduced": "0"
        },
        {
            "fixed": "9.15"
        }
    ]
}

Affected versions

Other
REL-1_0
REL-1_0-BETA1
REL-1_0-BETA2
REL-1_0-BETA3
REL-1_0-BETA4
REL-1_0-RC1
REL-1_1
REL-1_2
REL-1_3
REL-1_4
REL-1_5
REL-1_6
REL-2_0
REL-2_0-RC1
REL-2_0-RC2
REL-2_1
REL-3_0
REL-3_1
REL-3_2
REL-3_3
REL-3_4
REL-3_5
REL-3_6
REL-4_0
REL-4_1
REL-4_10
REL-4_11
REL-4_12
REL-4_13
REL-4_14
REL-4_15
REL-4_16
REL-4_17
REL-4_18
REL-4_19
REL-4_2
REL-4_20
REL-4_21
REL-4_22
REL-4_23
REL-4_24
REL-4_25
REL-4_26
REL-4_27
REL-4_28
REL-4_29
REL-4_3
REL-4_30
REL-4_4
REL-4_5
REL-4_6
REL-4_7
REL-4_8
REL-4_9
REL-5_0
REL-5_1
REL-5_2
REL-5_3
REL-5_4
REL-5_5
REL-5_6
REL-5_7
REL-6_0
REL-6_1
REL-6_10
REL-6_11
REL-6_12
REL-6_13
REL-6_14
REL-6_15
REL-6_16
REL-6_17
REL-6_18
REL-6_19
REL-6_2
REL-6_20
REL-6_21
REL-6_3
REL-6_4
REL-6_5
REL-6_6
REL-6_7
REL-6_8
REL-6_9
REL-7_0
REL-7_1
REL-7_2
REL-7_3
REL-7_4
REL-7_5
REL-7_6
REL-7_7
REL-7_8
REL-8_0
REL-8_1
REL-8_10
REL-8_11
REL-8_12
REL-8_13
REL-8_14
REL-8_2
REL-8_3
REL-8_4
REL-8_5
REL-8_6
REL-8_7
REL-8_8
REL-8_9
REL-9_0
REL-9_1
REL-9_10
REL-9_11
REL-9_12
REL-9_13
REL-9_14
REL-9_2
REL-9_3
REL-9_4
REL-9_5
REL-9_6
REL-9_7
REL-9_8
REL-9_9

Database specific

source
"https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-7820.json"