Skip to content

chore(deps): upgrade ratatui to 0.30 (RUSTSEC-2026-0253) - #2589

Open
1688mengdie wants to merge 3 commits into
GCWing:mainfrom
BitFun-SIG:fix/security-ratatui-lru-rustsec-0253
Open

chore(deps): upgrade ratatui to 0.30 (RUSTSEC-2026-0253)#2589
1688mengdie wants to merge 3 commits into
GCWing:mainfrom
BitFun-SIG:fix/security-ratatui-lru-rustsec-0253

Conversation

@1688mengdie

Copy link
Copy Markdown

Summary

cargo audit reports the locked lru dependency as unsound:
RUSTSEC-2026-0253 (later advisories reference RUSTSEC-2026-0002).
LruCache::pop is not panic-safe; when an eviction happens while a
panic is unwinding, the cache can be left inconsistent, leading to a
use-after-free or double free. Cargo.lock on main pins lru 0.12.5
through ratatui 0.29.0, and the advisory requires lru >= 0.18.2,
which ratatui 0.29 cannot satisfy because it pins lru ^0.12.

On the CLI TUI startup path, ratatui renders the interactive
interface; a panic during eviction on that path could trigger the
unsound behavior.

This PR upgrades ratatui from 0.29 to 0.30: ratatui-core 0.1.2
requires lru ^0.18, which resolves lru to 0.18.2 and closes the
advisory. The upgrade requires two mechanical follow-ups, included in
the same commit because the intermediate states do not compile: the
bitflags pin is relaxed from =2.11.1 to ^2 as required by
ratatui-core 0.1.2, and the CLI startup loop carries an explicit
B::Error: Send + Sync + 'static bound for the new associated Error
type on the Backend trait. Only the CLI TUI startup path consumes
this API.

Fixes #2587

Type and Areas

Type: dependency

Areas: CLI TUI dependency

Verification

  • cargo check --locked -p bitfun-cli --jobs 4 — passed (0 errors; 19 pre-existing warnings unchanged).
  • cargo tree --locked -i lru --depth 1 — resolved lru v0.18.2 through ratatui-core v0.1.2; cargo tree --locked -i ratatui shows ratatui v0.30.2 consumed by the CLI.
  • cargo test -p bitfun-cli --jobs 4 — 685 lib tests passed; 3 pre-existing failures (plugin_source_cli) are identical on the baseline commit (same names, same panic locations), so they are unrelated to this change.
  • cargo fmt --check -p bitfun-cli — one pre-existing diff in peer_host/commands/dialog.rs, byte-identical on the baseline commit; no formatting change from this PR.
  • Full workspace build and interactive TUI scenarios were not run locally; repository CI remains the cross-platform verification source.

Reviewer Notes

  • ratatui 0.30 is the first 0.30.x release line; the lockfile resolves it to 0.30.2 and lru to exactly 0.18.2 (the advisory's minimum fixed version).
  • The only source change is the explicit trait bound in src/apps/cli/src/ui/startup.rs; no behavior change is intended.
  • No UI change beyond the TUI upgrade itself; no migration or persisted-shape compatibility work is applicable.
  • Rollback is the inverse of the three-file change.

Checklist

  • This PR is focused and does not include secrets, temporary prompts, generated scratch files, or unrelated artifacts.
  • Relevant verification is recorded above, or skipped checks are explained.
  • User-facing strings, docs, and locales are updated where applicable. (Not applicable: no user-facing change.)

This is an AI-assisted change.

1688mengdie and others added 3 commits August 28, 2026 09:50
The locked lru 0.12.5 pulled in by ratatui 0.29 is unsound
(RUSTSEC-2026-0253, later advisories reference RUSTSEC-2026-0002):
LruCache::pop is not panic-safe, and eviction can cause a use-after-free
or double free. The advisory requires lru >= 0.18.2, which ratatui 0.29
cannot satisfy because it pins lru ^0.12.

Upgrade ratatui 0.29 -> 0.30 (ratatui-core 0.1.2 requires lru ^0.18,
resolving lru to 0.18.2) and relax the bitflags pin from =2.11.1 to ^2,
which ratatui-core 0.1.2 needs. ratatui 0.30 adds an associated Error
type to the Backend trait, so the CLI startup loop now carries an
explicit `B::Error: Send + Sync + 'static` bound. Only the CLI TUI
startup path consumes this API.

Test: cargo check --locked -p bitfun-cli --jobs 4; cargo tree --locked -i lru --depth 1; cargo test -p bitfun-cli --jobs 4; cargo fmt --check

AI: lightly tested
The ratatui 0.30 upgrade (2cdc3b2) left two crossterm versions in the
lockfile: the CLI kept a direct crossterm 0.28 dependency while
ratatui-crossterm 0.1.2 pulls crossterm 0.29. The split also changed the
cursor-position path on unix: ratatui 0.30's draw pipeline queries the
cursor position through crossterm 0.29, which sends a CSI 6n device
status report and blocks until the terminal answers. Inside the PTY test
harness no terminal emulator answers the report, so the startup draw
failed with "The cursor position could not be read within a normal
duration" and the interactive TUI exited before rendering its first
prompt. Windows passed because its cursor path uses the console API
instead of the 6n round-trip, and the headless exec tests passed because
they never draw.

Unify the CLI on crossterm 0.29 so the direct dependency and the
ratatui-crossterm adapter share one version. The CLI only uses the
event and terminal modules, which are API-compatible between 0.28 and
0.29, so no source changes are required. cargo tree now resolves a
single crossterm 0.29.0 for both the CLI input path and the ratatui
backend, keeping the event-loop and cursor state in one instance.

Test: cargo check --locked -p bitfun-cli --jobs 4; cargo test -p bitfun-cli --jobs 4; cargo tree --locked -i crossterm --depth 3

AI: lightly tested
The ratatui 0.30 upgrade (2cdc3b2) made `Terminal::clear` snapshot and
restore the cursor position around the screen clear, and the startup page
clears the terminal right after rendering the loading placeholder. On
unix this reaches `crossterm::cursor::position`, which writes a CSI 6n
device status report and blocks until the terminal answers; the previous
ratatui 0.29 clear never queried the backend. Inside the PTY test
harness no terminal emulator is attached, so the query went unanswered
and the CLI exited with "The cursor position could not be read within a
normal duration" before rendering its first prompt. Windows kept passing
because its cursor path uses the console API instead of the 6n
round-trip, and the headless exec tests kept passing because they never
draw. Unifying crossterm at 0.29 (da74153) removed the dual-instance
split but could not remove the 6n round-trip itself, so the ubuntu and
macos failures reproduced unchanged.

Teach the PTY harness to act as the missing terminal emulator: the
existing reader loop now scans the CLI output for the 6n query and
answers it on the master side with a well-formed cursor position report.
The report value is arbitrary because the CLI clears the screen and
every draw emits explicit cursor movement afterwards. The writer handle
is shared through an Arc<Mutex<>> between the reply path and the test
input path since portable-pty allows taking the writer only once, and a
short tail of each scanned chunk is carried over so a query split across
read boundaries is still answered. The harness change is test-only and
touches no production code.

Test: cargo check --locked -p bitfun-cli --jobs 4; cargo test -p bitfun-cli --jobs 4 --test terminal_process_contracts; cargo fmt --check

AI: lightly tested
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.

[Security]: RUSTSEC-2026-0253: lru 0.12.5 in Cargo.lock is unsound (use-after-free via LruCache eviction)

1 participant