- is_web_url sliced the string at byte 7/8, panicking (and killing every
session) when a remote host printed an OSC 8 or plain link with a
multi-byte character at that offset and the user hovered it. It now
compares bytes.
- Paste confirmation also triggers on control characters other than tab
(readline's C-o runs a line with no newline), and the preview shows
them escaped.
- Remote clipboard toasts escape control characters and state the line
count, so 'ls\ncurl … | sh' no longer reads as a harmless 'ls'.
- Inline images: dimensions are read from the header first and anything
over the 32 Mpx per-terminal budget is refused before decoding.
- Toasts: repeats extend the visible toast and at most 8 are kept, so
trigger or OSC 52 floods can't stall frames.
- The URL regex is compiled once.
- Enable eframe's 'links' feature: without it every 'open in browser'
(Cmd/Ctrl+click, GitHub repo links, the update link) was a silent
no-op. Adds webbrowser 1.2.4 to the lockfile.
Images sent with the iTerm2 inline protocol (imgcat and friends) are
decoded (PNG, JPEG, GIF first frame) and drawn at the cursor, sized from
the width/height arguments in cells, pixels or percent (aspect kept,
never wider than the terminal); the cursor moves below so text
continues after them. They are anchored to the same stable line index
as the shell-integration marks, scroll with the text and are dropped
with the scrollback or on clear.
Remote data, so decoding is bounded (8192 px a side, 256 MiB
allocation), OSC bodies are capped at 16 MiB, inline=0 downloads are
ignored, and each terminal keeps at most 32 Mpx of images, oldest
first. Sixel and kitty graphics are not implemented.
- Credential callbacks (SecretFn) now return Zeroizing<String>, as do the
session-only/pending caches they read and the RDP client's password,
so Nexus's own copies are wiped; a plain String copy is made only
where a library API needs one (SSH password auth, IRC, VNC, CredSSP).
- Release builds disable core dumps (RLIMIT_CORE 0) and, on Linux, mark
the process non-dumpable (PR_SET_DUMPABLE 0), which also blocks ptrace
attach and /proc/<pid>/mem reads by other processes of the same user.
Debug builds are unchanged so they stay debuggable. Verified on the
release binary: core limit 0, /proc/<pid>/{environ,mem} root-owned and
unreadable, local shells (including cwd capture) still work.
Closes the remaining parts of SEC-20261012-007 that the app controls;
egui's internal text buffers remain outside its reach.
The app now writes a diagnostic log to nexus.log in the data directory
(0600, rotated at 5 MiB): connection attempts and results, remote
closes, reconnect scheduling, host-key/certificate checks with the
policy applied, and credentials that couldn't be stored (kind only).
Credentials and terminal data are never logged. RUST_LOG sets the level
and also mirrors the log to stderr. The remaining eprintln! diagnostics
in storage and URL handling go through it too.
Session-only credentials (kept for a whole session so reconnects don't
re-prompt), credentials pending until a connection succeeds, and the
credential prompt's text buffer are now Zeroizing and wiped when
dropped, including when a prompt is cancelled or abandoned
(SEC-20261012-007, partial).
Still open: the values handed to the protocol clients are plain Strings
for the duration of authentication, egui keeps its own copies of typed
text, and no mlock/PR_SET_DUMPABLE is applied.
Every shared lock was std::sync::Mutex with lock().unwrap() (~150 sites),
so a panic in any session's reader or callback poisoned the lock and the
next UI frame panicked too, dropping every open session. Locks are now
parking_lot::Mutex (no poisoning; already in the dependency tree), and a
panic hook reports worker panics as an error toast instead of the session
silently stopping (F3, F4).