Skip to content

Upgrade sqlx to 0.9.0; keep RUSTSEC-2026-0459 ignore until 0.9.1 - #9

Open
Kenbak wants to merge 2 commits into
mainfrom
new/reverent-mccarthy-199a66
Open

Kenbak wants to merge 2 commits into
mainfrom
new/reverent-mccarthy-199a66

Conversation

@Kenbak

@Kenbak Kenbak commented Nov 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR upgrades sqlx from 0.8.6 to 0.9.0.

The RUSTSEC-2026-0459 exemption stays. sqlx 0.9.0 is the only 0.9 release on crates.io, and its sqlx-sqlite declares libsqlite3-sys >=0.30.1, <0.38.0. The lockfile therefore stays on libsqlite3-sys 0.30.1, which bundles SQLite 3.46. The fix needs 0.39 (SQLite 3.54). The wider <0.40 bound is already on sqlx main (transact-rs/sqlx#4502) and ships in 0.9.1 (transact-rs/sqlx#4517, not yet released). The audit.yml comment now says to remove the ignore with sqlx 0.9.1. The owner chose this option over pinning sqlx to an unreleased git revision.

Migration

  • Features: sqlite is replaced by sqlite-bundled + sqlite-unlock-notify. In 0.9, sqlite also enables deserialize and load-extension, so this keeps exactly the libsqlite3-sys feature set we had under 0.8 (bundled, unlock_notify, pkg-config, vcpkg).
  • Lockfile: rsa, pkcs1 and num-bigint-dig drop out of Cargo.lock entirely, because sqlx-mysql 0.9 no longer pulls them in. atomic-polyfill is also absent. The RUSTSEC-2023-0071 and RUSTSEC-2023-0089 ignores are probably unnecessary now; I left them as they are.
  • Other dependencies: whoami 1 → 2, md-5/sha1/sha2 0.11, and hashlink/flume bumps, all transitive through sqlx.

SqlSafeStr audit (45 sites)

sqlx 0.9 only accepts query strings that are &'static str or explicitly marked as audited (AssertSqlSafe). Each of the 45 compile errors was reviewed:

  • Static migration arrays (db.rs, db/bootstrap.rs): these now iterate by value, so each query is a &'static str and needs no assertion.
  • Merchant webhook list (api/auth.rs): the strings were already literals, so the .to_string() calls were dropped and they compile as &'static str.
  • Missing-column check (db/bootstrap.rs): the pragma_table_info query used to interpolate the table and column names. It now binds them as parameters (pragma_table_info(?) WHERE name = ?).
  • Marked AssertSqlSafe with a comment explaining why each is safe:
    • MERCHANT_COLS/PL_COLUMNS/PRICE_COLS/SUB_COLS column-list formats: compile-time constants only.
    • The admin webhook filter: joins only fixed column = ? fragments, and every value is bound.
    • The price-label IN (?,…): only placeholders are interpolated.
    • The belt-and-suspenders ALTER TABLE … ADD COLUMN: identifiers come from a fixed list.
    • PRAGMA table_info(…): ensure_columns now takes &'static str.
    • The invoices FK repair and the referral trigger recreation: they replay DDL read back from this database's own sqlite_master.

No request-derived value is interpolated into SQL anywhere.

Behaviour differences

  • App behaviour: none intended. Payment accounting is unchanged: integer zatoshis, the same SQL, and the same BEGIN IMMEDIATE transactions.
  • Upstream fixes:
    • When a transaction is dropped during BEGIN, sqlx now rolls it back correctly.
    • SQLite transaction-depth accounting is fixed for a bad custom begin command.
    • Pool::close now closes all connections before it returns.
  • Not included: the auto-rollback depth fix (fix(sqlite): reset transaction depth after SQLite rolls back on its own transact-rs/sqlx#4515) is still unreleased.

Verification

  • cargo test --locked: 136 passed. The 3 ignored tests need external fixtures and were already ignored. The repair tests, migration tests and the referral-guardrail migration test all pass.
  • python3 scripts/check-dependency-exposure.py: passes unchanged.
  • cargo audit --deny unmaintained --deny unsound --ignore RUSTSEC-2023-0071 --ignore RUSTSEC-2023-0089 --ignore RUSTSEC-2026-0459: passes. Without the 0459 ignore it fails, as expected, on libsqlite3-sys 0.30.1.

Not deployed.

kenbak wan added 2 commits November 14, 2026 20:39
sqlx 0.9 requires SqlSafeStr for query strings. Static migration arrays
now iterate by value (&'static str); webhook SQL is literal; the
pragma_table_info column check is fully bound. The remaining dynamic
sites interpolate only compile-time column lists, '?' placeholders,
fixed identifiers, or DDL read from this database's sqlite_master, and
are marked AssertSqlSafe with that justification.

Features are pinned to sqlite-bundled + sqlite-unlock-notify, matching
the 0.8 libsqlite3-sys feature set (0.9's 'sqlite' would add
deserialize and load-extension).

sqlx 0.9.0 still caps libsqlite3-sys < 0.38, so RUSTSEC-2026-0459 is
not fixed by this commit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant