Repository navigation
Three RUSTSEC advisories in the dependency tree, and Cargo.lock is untracked #18
Description
Tested against v0.1.2-alpha.1 (24c4fb7).
Advisories
cargo audit on a fresh resolve of the workspace:
RUSTSEC-2023-0071 rsa 0.9.10 Marvin attack, timing side channel
CVE-2023-49092, CVSS 5.9, no patched release exists
RUSTSEC-2026-0154 russh 0.46.0 unbounded 32-bit allocation
RUSTSEC-2026-0153 russh-cryptovec 0.7.3 unchecked CryptoVec allocation and growth
both CVE-2026-46673, CVSS 7.5, patched in >= 0.60.3
Plus seven warnings. proc-macro-error 1.0.4 and five unic-* crates are unmaintained, and glib 0.18.5 has an unsoundness advisory. All of those arrive through Tauri and GTK.
I confirmed the shipped binaries carry these exact versions by reading the panic-path strings out of the released macOS and Windows executables, so this is not only a lockfile question.
Notes on each:
rsahas no fixed version in any 0.9 line. It reaches the tree throughrussh-keys, and the timing channel applies when Clavyn signs with a stored RSA key. Users on Ed25519 keys are not affected.- The two russh advisories describe frame-size handling in the SSH agent protocol. Clavyn rejects agent auth explicitly at
connection.rs:72, which narrows the described vector, butrussh-cryptovecsits on the general allocation path and 0.46.0 is fourteen minor versions behind. - Moving to
russh0.60.3 is not a version bump. The 0.5x line reorganisedrussh::keysand changed theHandlersignatures, soconnection.rs,session.rsandsftp.rsall need work.
Cargo.lock is not tracked
.gitignore lists Cargo.lock. For a workspace that produces shipped binaries the lockfile belongs in the repository. Without it:
- every release resolves around 400 crates fresh, so two builds of the same tag can differ
- a compromised or broken patch release of any transitive dependency lands in the next build with no diff to review
cargo auditresults are not reproducible, because there is no recorded tree to audit
The npm side already does this correctly. desktop/package-lock.json and desktop/e2e/package-lock.json are both tracked, and CI runs npm ci.
No dependency gate in CI
.github/workflows/ci.yml runs cargo check, cargo test, vue-tsc, vitest and vite build. There is no cargo audit, no cargo deny, no cargo clippy, no npm audit and no Dependabot config. Nothing in the pipeline would have surfaced the three advisories above.
For reference, npm audit --omit=dev on desktop/ reports zero vulnerabilities today, so the production JavaScript tree is clean. The dev tree has five, including a critical in vitest that only applies when the Vitest UI server is listening, so it does not reach shipped code.
Suggested fix
Two steps, because they carry very different risk:
- Track
Cargo.lockand add acargo auditjob to CI, with anaudit.tomlthat ignores the three current advisories and a comment pointing back here. The job then catches anything new from day one. - Upgrade
russhto 0.60.3 or later as its own change, with the API migration and a manual connection test.
I have a PR for step 1.
Activity
Sadykhzadeh commentedon Sep 10, 2026
Working through the suppressions this issue's step 1 shipped, two corrections to
the notes above — including one to this issue's own text — and a PR for the part
that turns out to be live: #29.
The two russh advisories are not the same finding. The body here says "the
two russh advisories describe frame-size handling in the SSH agent protocol".
That is right for
RUSTSEC-2026-0154and wrong forRUSTSEC-2026-0153.RUSTSEC-2026-0154'spackageisrussh, and its description is entirelyagent-protocol frame-size validation. The suppression note is correct, and in
fact understates the case: russh 0.46.0 has no agent implementation of its own.
The code the advisory describes lives in
russh-keys 0.46.0(
src/agent/client.rs,src/agent/server.rs), which carries no advisory atall, and
connection.rs:72rejects agent auth beforeclient::connecteitherway.
RUSTSEC-2026-0153is the one aboutCryptoVecin "transport and compressionbuffers". Its note in
.cargo/audit.tomlwas the un-justified one — just"Fixed in 0.60.3, which is part of the russh 0.5x/0.6x API break", with no
vector note, which the file's own header requires.
Of -0153's two paths, only one is live in 0.46.0.
russh-0.46.0/src/cipher/mod.rsrejects anypacket whose declared length exceeds
MAXIMUM_PACKET_LEN(256 KiB) before itresizes the read buffer.
russh-0.46.0/src/compression.rsresizes its outputbuffer to
output.len() * 2on every partial-output status from flate2, withno ceiling.
russh-cryptovec-0.7.3panics explicitly when its realloc returnsnull, and the release profile's
panic = "abort"turns that into processdeath, so every other open session dies with the one under attack.
It is reachable:
flate2is a default feature andConfig::default()offers[none, zlib, zlib@openssh.com]. Client preference meansnonewins against anormal server, but a server advertising zlib alone forces compression on. So the
honest framing is a malicious or compromised server (or a hostile endpoint on a
TOFU first connect) aborting the client — medium, not the advisory's 7.5, and no
RCE or loss of confidentiality or integrity.
#29 builds russh with
default-features = false, which dropsflate2— itsonly default feature — and compiles the growth loop out entirely; the no-flate2
decompressis a pass-through.clavyn-coreis russh's only dependent, sonothing unifies the feature back on. Clavyn never negotiates compression. The PR
also rewrites the -0153 note with the real residual, adds
review-bydatesenforced by a new expiry check in the audit job, pins the
cargo-auditversionCI builds, reports the seven informational advisories in a non-blocking step, and
adds the back-reference to this issue that b252e52's message promised.
The 0.46 → 0.60 upgrade stays here — #29 deliberately does not attempt it.
Sadykhzadeh commentedon Oct 2, 2026
Status
Everything here except the
rsaadvisory itself is done.Cargo.lock is tracked. It is in the repository and CI resolves against it.
The two russh advisories are gone. #98 migrated the workspace to
russh0.63.3, which tookrussh-cryptovecandrussh-keyswith it, so RUSTSEC-2026-0154 and RUSTSEC-2026-0153 no longer apply. As noted here, that was not a version bump —connection.rs,session.rsandsftp.rsall moved with it.There is a dependency gate in CI. The
security-auditjob runscargo audit,npm audit --omit=devondesktop/, and reports the development advisories separately without failing on them..github/dependabot.ymlcovers cargo, npm and GitHub Actions.RUSTSEC-2023-0071 is suppressed with a review date, not silently.
audit.tomlcarries the one entry, with why it is there — norsarelease fixes it, it reaches the tree through russh'srsafeature, which stays on so existing RSA keys keep working, and it only applies when signing with a stored RSA key.scripts/verify/check-audit-expiry.mjsruns in the same job and fails the build oncereview-by: 2026-12-31passes, so the suppression cannot sit there unexamined.audit.tomlpoints at this issue as its tracking issue, so leaving it open: the remaining work is to drop the suppression when anrsarelease fixes the Marvin attack, or when russh no longer needs that feature.Sadykhzadeh commentedon Oct 16, 2026
Status on current
main:Cargo.lock: tracked and in sync;cargo metadata --lockedpasses, and Build against the committed Cargo.lock, bound CI jobs, and keep the updater key out of local release builds #146 enforces--lockedin CI.russh-keysis out of the tree.rsa 0.10.0-rc.18, with no fixed release. It is the only entry in.cargo/audit.toml, withreview-by: 2026-12-31, which CI enforces. It still applies only to signing with a stored RSA key.security-auditred. Consolidate the four open dependency bumps and clear the npm production audit #128 now updates both. With that lockfilecargo auditreports 0 vulnerabilities, plus 2 informational warnings that don't gate.I'm keeping this open as the tracking issue for the rsa advisory, since
audit.tomllinks here.