Engineer working on a laptop connected to a device test rig, surrounded by wiring harnesses and test hardware

Firmware vulnerabilities & fixes

SQLite vulnerabilities in embedded firmware: finding the version, triaging CVEs and hardening the build

Last updated:

SQLite vulnerabilities in embedded firmware matter mainly when an attacker can run SQL of their own or hand the device a crafted database file: SQLite's CVE page, updated 2026-11-11, says every historical SQLite vulnerability requires one of those two conditions. Finding them means locating every SQLite copy in the image, reading its version and source ID, and checking it against the SQLite release log (3.54.1, 16 October 2026 is current). Triage then asks whether untrusted input reaches SQL text, and the fix is an upgrade, a backport or a hardened build.

Key takeaways

  • SQLite turns up wherever firmware needs to keep structured data on flash without running a database server.
  • Every SQLite build carries two strings that identify it.
  • SQLite CVEs fall into a few families, and the conditions each family needs decide whether it applies to a device.
  • Almost all of them, and that is the main triage question for a device.

Where does SQLite ship in a device image?

SQLite turns up wherever firmware needs to keep structured data on flash without running a database server. Typical places are configuration stores behind a web interface, event and audit logs, metering or sensor histories, user and certificate stores, and application data in management agents, media and home-automation software. Scripting runtimes such as Python and PHP also link it for their database modules.

It often ships more than once. SQLite is distributed as "the amalgamation", which the SQLite amalgamation page describes as over 100 source files "concatenated into a single large file of C-code named "sqlite3.c"" that "contains everything an application needs to embed SQLite". Because one C file is easy to drop into any project, vendors and third-party applications compile their own copy rather than linking the shared library. A single image can carry a shared library from the build system and several statically linked copies at different versions, and the package manager only knows about the first.

The build system decides the shared copy. On 2026-11-14 Buildroot's sqlite package recipe pinned version 3.54.1 and set SQLITE_CPE_ID_VENDOR = sqlite, so the package metadata Buildroot exports names the same CPE vendor that NVD uses for SQLite. Optional features such as FTS3, RTREE and STAT4 are separate Buildroot options, which matters for triage because several CVEs live in those extensions. Our Yocto and Buildroot SBOM guide covers reading this from the build rather than the binary.

How do you find the SQLite version in a binary or package manifest?

Every SQLite build carries two strings that identify it. The run-time version documentation says the sqlite3_version[] constant holds the version text, such as 3.54.1, and sqlite3_sourceid() returns the source ID: "the date and time of the check-in (UTC) and a SHA1 or SHA3-256 hash of the entire source tree". The Release History prints the source ID for each release; 3.54.1's is 2026-10-16 14:45:20 555e07ef..., and 3.50.2's starts 2025-06-28 14:00:48 2af157d7.... The documentation adds that if the amalgamation was edited, "the last four characters of the hash might be different", so match on the date and the leading hash characters.

Evidence Where it is What it tells you
Shared library name libsqlite3.so.0 in the root file system; readelf -d on each program lists it as a dependency Which programs a library upgrade fixes
Version string 3.x.y text in the read-only data of any ELF that contains SQLite The upstream release, for shared and static copies alike
Source ID Date, time and 64-character hash, matched against the release log The exact check-in, and whether the amalgamation was edited
Package database or build manifest opkg status file, Yocto image manifest, Buildroot legal-info and SBOM output Upstream base version plus the distribution patch level
Compile options PRAGMA compile_options on a running device, or option names in the binary Which extensions (FTS3, FTS5, session, zipfile) are built in

A practical sequence:

  1. Search every ELF file for a string matching a date, a time and a 64-hex-character hash, and for the text SQLite format 3 that opens every database file; each executable with a source ID outside libsqlite3.so is a separate copy to track.
  2. Look up each source ID in the release log to get the release, and record the copies as separate components with their own versions.
  3. Read the package database or build manifest for the shared library, and treat its version as the upstream base: distributions backport fixes without changing it, as the patching section below shows.
  4. Record which extensions each copy has. The PRAGMA documentation says PRAGMA compile_options "returns the names of compile-time options used when building SQLite", without the SQLITE_ prefix, so ENABLE_FTS3 in the output means FTS3 is compiled in.

Our firmware SBOM guide covers turning this into a component inventory.

Which SQLite CVE classes should a device maker know?

SQLite CVEs fall into a few families, and the conditions each family needs decide whether it applies to a device. The examples below are the ones scanners most often report against embedded images.

Query-parser and SQL-function bugs: CVE-2025-6965 and CVE-2019-19646

Most SQLite CVEs are memory errors or crashes triggered by an unusual SQL statement. CVE-2025-6965 is the current example: the CVE description says that in SQLite before 3.50.2 "the number of aggregate terms could exceed the number of columns available", which "could lead to a memory corruption issue". The 3.50.2 entry in the release log reads "Raise an error early if the number of aggregate terms in a query exceeds the maximum number of columns", and SQLite's Vulnerabilities page says that "an attacker who can inject arbitrary SQL statements into an application might be able to cause an integer overflow resulting in a read off the end of an array".

CVE-2019-19646, fixed in 3.31.0, shows the lower end of the family. The SQLite page says PRAGMA integrity_check "might cause the byte-code for a prepared statement to loop indefinitely", which could enable a denial of service, and adds that "this is not a vulnerability, as there are countless perfectly valid SQL queries" that run "essentially forever". The same release fixed a batch of NULL-pointer and uninitialised-pointer reads, all listed on that page as "Malicious SQL statement causes..." with denial of service as the impact.

FTS3 shadow-table corruption: Magellan, CVE-2018-20346

FTS3 is SQLite's full-text search extension, and it stores its index in ordinary "shadow tables". CVE-2018-20346, published by Tencent Blade as Magellan, is described as an integer overflow "and resultant buffer overflow" in SQLite before 3.25.3 "when the FTS3 extension is enabled", triggered by "FTS3 queries that occur after crafted changes to FTS3 shadow tables", allowing code execution "by leveraging the ability to run arbitrary SQL statements (such as in certain WebSQL use cases)". The attack writes to the index tables directly with SQL and then queries the corrupted index.

SQLite's response went beyond the patch. SQLite 3.26.0 (1 December 2018) "added the SQLITE_DBCONFIG_DEFENSIVE option which disables the ability to create corrupt database files using ordinary SQL" and "added support for read-only shadow tables" when defensive mode is on, according to the release log. A copy older than 3.25.3 with FTS3 compiled in is the case to look for; a copy built without FTS3 does not contain the vulnerable code.

Large-string bugs in the C API: CVE-2022-35737

Some SQLite bugs are reachable only through C function arguments of extreme size. SQLite's page says CVE-2022-35737, fixed in 3.39.2, "is only accessible when using some of the C-language APIs" and "cannot be reached using SQL nor can it be reached by providing SQLite with a corrupt database file"; it needs "very long string inputs (greater than 2 billion bytes in length)". Trail of Bits, who disclosed it, found that the bug is in SQLite's printf family with the %Q, %q or %w format types, that it "is exploitable on 64-bit systems", and that arbitrary code execution was confirmed only when the library was built without stack canaries.

On most embedded targets this needs a program that copies an unbounded network input of more than 2 GB into a sqlite3_snprintf or sqlite3_mprintf call. Debian rated the CVE "unimportant" in its tracker. Record the reasoning for each copy rather than assuming: a 64-bit gateway with plenty of RAM that formats SQL from uploaded files is a different case from a 32-bit sensor.

Extension, shell and wrapper CVEs

A large share of CVEs that mention SQLite are about something else. SQLite's table marks CVE-2023-7104 as a bug in the session extension, "only reachable by applications that recompile SQLite using the -DSQLITE_ENABLE_SESSION compile-time option"; CVE-2025-70873 is in the zipfile extension, "not a part of standard SQLite but usually included in builds of the CLI"; CVE-2022-46908 is in the command-line shell's --safe option. Others are filed against applications or language bindings that use SQLite, such as the SQLite JDBC library (CVE-2023-32697), and the table lists them as "Not a bug in SQLite". Whether a device ships the sqlite3 shell, which extensions are compiled in, and which wrapper library its applications use decides whether these apply.

Which SQLite bugs need attacker-controlled SQL to matter?

Almost all of them, and that is the main triage question for a device. SQLite's Vulnerabilities page says every historical vulnerability needs either an attacker who "can submit and run arbitrary SQL statements" or one who "can submit a maliciously crafted database file to the application". In most applications the first condition means an SQL injection bug in the application, which the page calls "a separate bug" and "a special case of a Remote Code Execution (RCE) vulnerability".

On a device, look for these paths:

  • SQL built from input. Web-interface handlers, CGI scripts, REST or MQTT handlers that paste request fields into SQL text instead of using bound parameters. This is the classic injection path; our input handling weaknesses guide covers fixing it.
  • Imported database files. Configuration restore, backup import or data-logger uploads that accept a .db file from a user and open it. This meets the second condition even with no injection bug.
  • Diagnostic consoles. A debug page or support shell that runs SQL typed by the user, or the sqlite3 command-line tool reachable over a remote shell.
  • Fixed SQL on trusted data. A program that only runs its own SQL on a database it created, on a read-only partition or in memory. CVEs that need attacker SQL do not apply here, though CVE-2022-35737-style C-API bugs still depend on what the program passes in.

CVE-2022-35737 is the main exception to the SQL condition. It needs neither SQL nor a crafted file, only an oversized string argument from the application, so check it against the C code that calls SQLite's formatting functions.

Where does SQLite publish its CVE notes?

SQLite publishes on its own site, and its developers are explicit about how they treat CVEs. The Vulnerabilities page has a "Status Of Recent SQLite CVEs" table with the fixing release and a comment per CVE. The same page states "The SQLite developers do not write CVEs" and "the SQLite developers do not track CVEs", and warns "You should not assume that a CVE about SQLite contains authoritative information". It also invites reports of missing CVEs on the SQLite Forum so they can be added to the table.

Use three sources together:

  1. The Vulnerabilities pagefor the developers' assessment and the fixed release; the table starts in 2019, so older CVEs such as Magellan are covered by distribution trackers and the release log.
  2. The [Release History](https://www.sqlite.org/changes.html)for what each release fixed and its source ID. Some entries name the CVE, as 3.39.2 does for CVE-2022-35737; others describe the fix without a CVE number, as 3.50.2 does for CVE-2025-6965. The newest release, 3.54.1, opens with "Fix a possible heap-buffer overflow on 32-bit builds", noting that "64-bit builds are not affected", which matters for 32-bit ARM and MIPS devices.

On 2026-11-13 CISA's KEV catalog (version 2026.11.13, 1,781 entries) listed no SQLite CVE. FIRST EPSS scores on the same date were 0.735 for CVE-2025-6965, 0.236 for CVE-2022-35737, 0.102 for CVE-2018-20346 and 0.074 for CVE-2019-19646. EPSS is a probability of exploitation activity, so use it to order the CVEs a device can reach; our KEV and EPSS prioritization guide explains both.

How do compile-time options harden SQLite in firmware?

A device maker who compiles SQLite controls most of its attack surface through build flags. SQLite's Defense Against The Dark Arts page lists the steps for applications that accept untrusted SQL, and most map to compile-time or start-up settings.

Setting What it does Source
-DSQLITE_DEFAULT_DEFENSIVE Turns on the defensive flag for every new connection, without a runtime call SQLite main.c adds SQLITE_Defensive to the default flags when the macro is defined
SQLITE_DBCONFIG_DEFENSIVE at runtime Disables PRAGMA writable_schema=ON, PRAGMA journal_mode=OFF, PRAGMA schema_version=N, writes to sqlite_dbpage and "direct writes to shadow tables" Connection configuration options
-DSQLITE_MAX_LENGTH=N or sqlite3_limit() Caps the size of any string or BLOB; the default is 1,000,000,000 bytes Limits In SQLite
Leave out SQLITE_ENABLE_FTS3_TOKENIZER Keeps the two-argument fts3_tokenizer() disabled, as it has been by default since 3.11.0 Compile-time options
Do not enable FTS3, FTS5, session or zipfile unless used Removes the code behind extension CVEs such as Magellan and CVE-2023-7104 Vulnerabilities page and compile-time options
-DSQLITE_OMIT_LOAD_EXTENSION Omits "the entire extension loading mechanism", so SQL cannot load a shared library Compile-time options
-DSQLITE_DQS=0 Disables double-quoted string literals, the setting SQLite calls "recommended" Compile-time options

The limits matter more on small devices. The security page suggests a "high-security value" of 1,000,000 bytes for LIMIT_LENGTH, against the default of 1,000,000,000, and warns that on "a processor with limited stack space" LIMIT_EXPR_DEPTH and LIMIT_TRIGGER_DEPTH should be small values "such as 10" to stop deep recursion from overflowing the stack. The limits page adds that "in security-sensitive applications it is best not to try to increase the maximum string and blob length", and a SQLITE_MAX_LENGTH far below 2 GB keeps oversized strings out of SQL values.

On FTS3 tokenizers, the compile-time options page warns that if attackers "are able to run the two-argument version of fts3_tokenizer() with an arbitrary second argument, they could crash or take control of the process", because that argument is a function pointer. Leave SQLITE_ENABLE_FTS3_TOKENIZER out of the build and do not call sqlite3_db_config() with SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER unless an application needs a custom tokenizer. Where an application must run user-supplied SQL, the security page also recommends sqlite3_set_authorizer() to reject statements such as CREATE and DROP.

How does a device maker update or backport SQLite?

Upgrading to the current release is the simplest fix. Upgrading the shared library through Yocto or Buildroot fixes every program that links it dynamically. Each statically linked copy needs its own rebuild with the new amalgamation, which is why the inventory step matters. Applications from third parties that bundle SQLite need an update from their supplier.

Backporting is what Linux distributions do, and it explains why a version number alone misleads scanners. The Debian security tracker lists CVE-2025-6965 as fixed in bookworm's 3.40.1-2+deb12u2, a 3.40.1 package, although the upstream fix arrived in 3.50.2. Ubuntu lists it fixed in 3.37.2-2ubuntu0.5 for 22.04 LTS and 3.45.1-1ubuntu2.4 for 24.04 LTS. Both trackers point to the same upstream check-in on sqlite.org. A device maker on an older SQLite can apply that check-in to the amalgamation the same way, then record the patch so that customers and scanners see the backport.

Steps for a backport:

  1. Find the fix check-in for the CVE: the Vulnerabilities page and distribution trackers link it.
  2. Apply it to the SQLite copy the product ships, rebuild, and run the application's own tests against the patched library.
  3. Record the patched component in the SBOM with a patch note, and publish the decision for each version-matched CVE that does not apply, for example in OpenVEX, with the reason (extension not compiled in, no attacker SQL path, fix backported).
  4. Confirm the shipped image contains the change; our firmware diffing and patch analysis guide covers comparing two builds.

Related library guides: zlib, Expat and libxml2, glibc, uClibc and musl and embedded web servers, which are often the components that pass request data into SQL.

AI-assisted analysis: what SoftWSP actually runs

SoftWSP's automated scan unpacks a firmware image, catalogs the software components it can identify in the extracted file system, and records each one's name, version and identifiers. Where the image carries identifiable SQLite version evidence, that component is matched against CVE records, CISA's KEV catalog and FIRST's EPSS scores. This matching is deterministic code: the code scores, and AI narrates.

AI writes the plain-language explanation on top of that matching: which SQLite CVEs matched, which are KEV-listed or have a high EPSS score, and what version evidence they rest on, with every sentence citing the component, version and record behind it. An engineer reviews every finding before the report is delivered. The judgements this guide describes as manual stay with that engineer: whether a statically linked copy exists beside the shared library, whether untrusted input reaches SQL text or a database file is imported, which extensions are compiled in, whether defensive mode and lowered limits are set, and whether a vendor backport already closes a version-matched CVE.

For a specific image, see device & firmware security services.

This guide draws on SQLite's Vulnerabilities page, Release History, compile-time options, limits, defensive-use, version and PRAGMA documentation and the SQLite source mirror, the Trail of Bits CVE-2022-35737 write-up, the Debian and Ubuntu CVE trackers, Buildroot's sqlite recipe, CISA's KEV catalog (version 2026.11.13) and FIRST EPSS data dated 2026-11-13, all read directly on 2026-11-14.

Put this guide to work

Frequently asked questions

How do I find the SQLite version inside a firmware image?

Search every ELF file in the unpacked root file system, not only libsqlite3.so. SQLite compiles its version string (for example "3.54.1") and its source ID into the library; the source ID is the check-in date and time followed by a 64-character SHA3-256 hash, such as "2026-10-16 14:45:20 555e07ef...". Because the SQLite release log publishes the source ID for each release, a strings search for that date-plus-hash pattern identifies the exact release even in a statically linked copy. Then compare it with the opkg database or the Yocto or Buildroot manifest, which give the upstream base version and any distribution patch level.

Which SQLite CVEs actually matter on a device?

Mostly the ones an attacker can reach. SQLite's own CVE page says every historical SQLite vulnerability needs the attacker to run arbitrary SQL statements or to hand the application a crafted database file. CVE-2025-6965 (fixed in 3.50.2) and Magellan, CVE-2018-20346 (FTS3, fixed in 3.25.3), both need attacker-controlled SQL. CVE-2022-35737 (fixed in 3.39.2) needs a string of more than 2 billion bytes passed to certain C interfaces. CVE-2019-19646 is a PRAGMA integrity_check loop that only causes a denial of service. A device that builds SQL from web-interface, API or MQTT input without bound parameters, or that imports database files from users, meets those conditions.

Is any SQLite CVE in CISA's KEV catalog?

No. CISA's Known Exploited Vulnerabilities catalog version 2026.11.13 (1,781 entries) lists no SQLite CVE. On 2026-11-13 FIRST EPSS gave CVE-2025-6965 a score of 0.735, CVE-2022-35737 0.236, CVE-2018-20346 0.102 and CVE-2019-19646 0.074. EPSS estimates the probability of exploitation activity across the internet, so use it to order work among the CVEs a device can actually reach, not as a severity score.

Where does SQLite publish its security fixes?

On two pages on sqlite.org. The Vulnerabilities page has a table of recent SQLite CVEs with the release that fixed each one and the developers' comments, including CVEs they consider not bugs in SQLite. The Release History page lists each release's fixes and its SQLITE_SOURCE_ID and SHA3-256 hash. The developers state that they do not write CVEs or track them, so a CVE can appear weeks after the fix and may not match their assessment.

Does SoftWSP decide whether a SQLite CVE is reachable in my firmware?

No, not automatically. SoftWSP's scan identifies software components and versions in the unpacked firmware and matches them against CVE records, CISA KEV and FIRST EPSS data; AI then writes a summary that cites the component, version and record behind each finding, and an engineer reviews it. Whether an application passes untrusted input into SQL text, which extensions are compiled in, whether defensive mode is set and whether a vendor backport covers a version-matched CVE is decided in that engineer review.

Sources

  1. SQLite: Vulnerabilities (status of recent SQLite CVEs)
  2. SQLite: Release History (3.54.1, 16 October 2026)
  3. SQLite: Compile-time Options
  4. SQLite: Limits In SQLite
  5. SQLite: Defense Against The Dark Arts
  6. SQLite: Run-Time Library Version Numbers (sqlite3_version, sqlite3_sourceid)
  7. SQLite: Database Connection Configuration Options (SQLITE_DBCONFIG_DEFENSIVE)
  8. SQLite: PRAGMA statements (compile_options)
  9. SQLite: The SQLite Amalgamation
  10. SQLite source mirror: main.c (SQLITE_DEFAULT_DEFENSIVE)
  11. Trail of Bits: Stranger Strings, an exploitable flaw in SQLite (CVE-2022-35737)
  12. Debian security tracker: CVE-2018-20346 (Magellan)
  13. Debian security tracker: CVE-2022-35737
  14. Debian security tracker: CVE-2025-6965
  15. Ubuntu security: CVE-2025-6965
  16. Buildroot: sqlite package recipe (sqlite.mk)
  17. CISA: Known Exploited Vulnerabilities (KEV) Catalog
  18. FIRST: Exploit Prediction Scoring System (EPSS)
Was this guide helpful?

In this cluster

SQLite vulnerabilities in embedded firmware: finding the version, triaging CVEs and hardening the build