Introduction
A SQL injection flaw in the NSA's Ghidra reverse engineering framework lets any authenticated BSim user escalate to PostgreSQL superuser privileges. The attacker injects SQL commands through a crafted username in the password change flow. Thousands of security researchers, malware analysts, and government teams rely on Ghidra's BSim feature for binary function similarity analysis, and for them this bug turns a routine credential change into a path to full database compromise.
Ghidra is a free, open-source software reverse engineering framework developed by the National Security Agency and publicly released in 2019. It has over 61,000 GitHub stars, is widely used by government agencies, private sector security teams, and independent researchers, and is the main free alternative to commercial tools like IDA Pro. BSim, the affected component, is Ghidra's built-in function similarity search framework. It uses a PostgreSQL backend to store and query binary function signatures.
Technical information
Root cause
The vulnerability is in the changePassword() method of the PostgresFunctionDatabase class in Ghidra's BSim feature. This method builds SQL ALTER ROLE statements with string interpolation, inserting the username directly between double-quote delimiters without any escaping.
Here is the vulnerable code from Ghidra 12.0.4 and earlier:
// VULNERABLE — Ghidra 12.0.4 and earlier buffer.append("ALTER ROLE \""); buffer.append(username); // username inserted verbatim, no escaping! buffer.append("\" WITH PASSWORD '"); for (char ch : newPassword) { if (ch == '\'') { buffer.append(ch); // manual single-quote doubling for password } buffer.append(ch); } buffer.append('\'');
The two inputs are treated differently. The password gets manual single-quote escaping, but the username is concatenated between double-quote delimiters with no escaping at all. A username containing a literal double quote character (") breaks out of the identifier quoting and allows arbitrary SQL injection into the ALTER ROLE statement.
Attack flow
The full CVSS v4.0 vector string is CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N. It describes a network-accessible, low-complexity attack with high impact on confidentiality, integrity, and availability.
The attack runs in four steps:
-
The attacker authenticates to the BSim server with any valid user credentials. This is the only prerequisite, and any user with BSim access qualifies.
-
The attacker sends a
PasswordChangenetwork message with a crafted username parameter containing embedded double quotes. For example, a username such asuser"; CREATE ROLE attacker SUPERUSER;--would break out of the intendedALTER ROLEstatement and inject a second command that creates a superuser account. -
The
PostgresFunctionDatabase.changePassword()method interpolates the malicious username into theALTER ROLEstatement and executes it against the PostgreSQL backend, without parameterized queries or prepared statements. -
The injected SQL commands run with the privileges of the database connection the BSim server uses. A successful injection lets the attacker escalate to PostgreSQL superuser status, which means full control over the database. The attacker can read, modify, or delete all data, create new database users, and run administrative functions.
CVSS scoring
| Metric | CVSS v3.x | CVSS v4.0 |
|---|---|---|
| Base Score | 8.8 (High) | 8.7 (High) |
| Attack Vector | Network | Network |
| Attack Complexity | Low | Low |
| Privileges Required | Low | Low |
| User Interaction | None | None |
| Confidentiality Impact | High | High (VC:H) |
| Integrity Impact | High | High (VI:H) |
| Availability Impact | High | High (VA:H) |
The CNA (VulnCheck) assessed the CVSS v4.0 score at 8.7, and the CVSS v3.x score is 8.8. Both describe a network-accessible, low-complexity, authenticated privilege escalation with high system impact.
Related vulnerability
Security bulletin SB20260515104 identifies a second, distinct SQL injection vulnerability in the BSim search filter types. This flaw fails to neutralize special elements in XML protocol messages sent over the BSim network query protocol, which allows injection of arbitrary SQL commands through a different attack surface. Organizations addressing CVE-2026-49498 should evaluate this related flaw as well.
Patch information
The vulnerability was fixed in Ghidra 12.1, released on May 13, 2026. The GitHub Security Advisory GHSA-vv7r-2rhf-5h7g explicitly lists the patched version as 12.1, and VulnCheck independently confirms the affected range as Ghidra 11.0 through versions prior to 12.1.
The patch targets the changePassword() method in Ghidra/Features/BSim/src/main/java/ghidra/features/bsim/query/client/PostgresFunctionDatabase.java. Here is the patched version from Ghidra 12.1:
// PATCHED — Ghidra 12.1 buffer.append("ALTER ROLE "); Utils.escapeIdentifier(buffer, username); // proper identifier escaping buffer.append(" WITH PASSWORD '"); Utils.escapeLiteral(buffer, new String(newPassword), true); // proper literal escaping buffer.append('\'');
The fix makes two changes:
-
For the username, the code no longer wraps the raw value in double quotes by hand. It calls
org.postgresql.core.Utils.escapeIdentifier(), the PostgreSQL JDBC driver's built-in utility, which escapes any embedded double quote characters by doubling them (e.g.,my"userbecomes"my""user"). That is the correct way to embed identifiers safely in PostgreSQL SQL statements. The patch adds an import fororg.postgresql.core.Utilsto support this. -
For the password, the hand-rolled single-quote escaping loop is replaced with
Utils.escapeLiteral(), the matching PostgreSQL JDBC utility for escaping string literals. The old manual escaping was functionally adequate, but the library function is more robust and consistent.
This is a textbook example of replacing ad hoc string escaping with well-tested library functions, a practice that eliminates an entire class of injection bugs. Users running Ghidra 11.0 through 12.0.x with a BSim PostgreSQL backend should upgrade to Ghidra 12.1 (or the latest 12.1.2 release) to apply this fix.
You can compare the vulnerable and patched source files directly:
Affected systems and versions
The vulnerability affects Ghidra versions 11.0 through 12.0.x (inclusive). Any Ghidra installation that uses the BSim feature with a PostgreSQL database backend is vulnerable. Installations using BSim with other database backends, and installations not using BSim at all, are not affected by this specific flaw.
The patched version is Ghidra 12.1, released May 13, 2026. The latest available release at the time of writing is Ghidra 12.1.2.
Vendor security history
Ghidra's past advisories show a recurring pattern of injection and trust-boundary vulnerabilities:
- CVE-2019-16941: An early vulnerability that let attackers compromise exposed systems while Ghidra's experimental mode was running, a risk that came from the tool's network-facing features.
- GHSA-j3xg-fc2p-4jc4 (Log4j): A remote code injection vulnerability in the Log4j library, from the Log4Shell crisis.
- GHSA-cqfj-5crw-rh6p (Command Injection in launch.sh): A command injection flaw where user-provided command-line arguments were passed to the Java application launch without sanitization.
- CVE-2026-4946 (Command Execution via Auto Generated Comments): Discovered by AHA! (Austin Hackers Anonymous) and the Mobasi Security Team, this high-severity flaw (CVSS 8.8) let a malicious binary trigger arbitrary command execution when an analyst clicked on auto-generated comments. The
CFStringAnalyzerextracted strings from Mach-O binaries, andAnnotation.javainterpreted@executedirectives, running commands viaProcessBuilderwithout confirmation. Patched in Ghidra 12.0.3. - SB20260515104 (Nine Vulnerabilities, May 2026): The current cluster includes two SQL injection flaws (one of them CVE-2026-49498), command injection in URL annotation handling, improper cryptographic signature verification in
PKIAuthenticationModule.authenticate(), deserialization of untrusted data in shared project connections, denial of service viaExportTrie.parseTrie(), path traversal inSameDirDebugInfoProvider, and two use-after-free vulnerabilities in decompilation code.
The NSA has followed a responsible disclosure and patching process, publishing security advisories through GitHub and coordinating with external researchers. Internal NSA development staff published the advisory for GHSA-vv7r-2rhf-5h7g, and external organizations such as Oceanit have also helped identify and resolve vulnerabilities. The researcher credited with discovering CVE-2026-49498 is Sean Nejad (@allsmog).
The NSA's Ghidra page acknowledges the risk directly. It states that "there are known security vulnerabilities within certain versions of Ghidra" and advises users to review security advisories before proceeding.
References
- NVD: CVE-2026-49498
- GitHub Security Advisory: GHSA-vv7r-2rhf-5h7g
- VulnCheck Advisory: Ghidra SQL Injection in PostgreSQL Password Change via Unescaped Username
- Ghidra Security Advisories (GitHub)
- Ghidra Releases (GitHub)
- Patched Source: PostgresFunctionDatabase.java (Ghidra 12.1)
- Vulnerable Source: PostgresFunctionDatabase.java (Ghidra 12.0.4)
- SB20260515104: Multiple Vulnerabilities in Ghidra
- NSA Ghidra Official Page
- CISA Known Exploited Vulnerabilities Catalog
- CVE-2026-4946: Ghidra Command Execution via Auto Generated Comments



