update: bump workspace deps and sync russh forks to upstream stable#203
Merged
Conversation
…table
bssh deps: lru 0.17→0.18 (lifetime fix), signal-hook 0.3→0.4 (only the unused low_level::pipe API changed), opentelemetry / opentelemetry_sdk / opentelemetry-otlp 0.31→0.32 (source-compatible at our LogExporter / SdkLoggerProvider / Resource builders + LogRecord call sites; the removed ExportConfig / HasExportConfig trio isn't used here), plus nix 0.31.2→0.31.3 and transitive pin-project / tower-http / zerofrom patches via cargo update.
bssh-russh 0.60.1→0.60.3: track upstream stable. Bump russh-cryptovec 0.59.0→0.60.3 (carries the CryptoVec hardening half of CVE-2026-46673) and aws-lc-rs 1.16.3→1.17.0. Manually forward-port the agent-frame-length-cap half of CVE-2026-46673 (commit a2d48a7) into src/keys/agent/{client,server}.rs — adds MAX_AGENT_FRAME_LEN = 256 KiB, factors out read_frame(), and rejects oversized frames with Error::AgentProtocolError before allocating. Recorded as patches/agent-frame-length-cap.patch so the next sync-upstream.sh run will auto-skip it via the reverse-apply dry-run check.
bssh-russh-sftp 2.1.1→2.1.2: full source sync to upstream 2.1.2. Upstream absorbed the original serde_bytes perf fix in protocol/{write,data}.rs and the matching serialize_bytes implementation; the patch is moved to patches/historical/ for provenance. The fork's remaining value-add is two pipelined File I/O helpers (write_all_pipelined / read_to_writer_pipelined) that drive reader→file and file→writer transfers with bounded in-flight chunks to hide per-request RTT; they were undocumented before and have now been re-ported on top of the new Features API — chunk size derives from features.limits.{write,read}_len or features.max_packet_len.saturating_sub({WRITE,READ}_OVERHEAD_LENGTH) instead of the removed MAX_*_LENGTH constants. Cargo.toml replaces flurry with dashmap, adds serde_bytes as a direct dep, keeps futures (used by our pipelined helpers' FuturesUnordered), and pins versions to upstream's set. The fork description now records both the absorbed perf fix and the still-custom pipelined helpers so future maintainers won't repeat the mistake of dropping the fork without realising the pipelined methods aren't in upstream.
Verification: cargo build, cargo check --all-targets, and cargo clippy -p bssh --bins -p bssh-russh-sftp --lib -- -D warnings all clean. Affected-module tests pass — server::audit::otel 5, ssh::config_cache 14, pty:: 195, ssh:: 280. cargo audit reports 0 vulnerabilities and 0 unmaintained/yanked warnings against the 1090-advisory database after the bumps.
5 tasks
inureyes
added a commit
that referenced
this pull request
May 18, 2026
The fork's inline test modules (src/client/test.rs, src/keys/mod.rs, src/tests.rs) were imported from upstream russh during the initial sync (commit 508aa3f, "Sync bssh-russh fork with upstream russh 0.60.0") but the matching [dev-dependencies] block was never copied across, so every `cargo test -p bssh-russh` since the fork's inception has failed with E0433 on `env_logger`, `tempfile`, and cascading E0282 type-inference errors where helper functions return `tempfile::TempDir`. The test target compiled exactly zero times under our manifest until now. Adds a minimal [dev-dependencies] block covering only what the imported tests actually reference: `env_logger = "0.11"` for `env_logger::try_init()` in `src/client/test.rs`, `tempfile = "3"` for `tempfile::tempdir()` / `tempfile::TempDir` in `src/keys/mod.rs` and `src/tests.rs`, and `tokio = { version = "1.52.1", features = ["process", "macros"] }` as an additive entry that merges with the main tokio dep to add the `process` feature (needed by the spawn-ssh-agent helpers that call `tokio::process::Command::new("ssh-agent").spawn()`) and the `macros` feature (needed by `#[tokio::test]`). Other tokio surfaces the tests use — `tokio::net::{TcpStream, UnixListener, UnixStream}`, `tokio::sync::oneshot`, `tokio::time::sleep` — were already covered by the main dep's `net`/`sync`/`time` features. Verification: `cargo test -p bssh-russh --lib` now runs 75 tests (0 failed, 0 ignored) covering the agent client/server roundtrip (test_agent, test_client_agent_{ed25519,rsa,openssh_rsa}, test_request_identities_full_with_keys_and_certs, test_sign_request_{,cert,cert_rsa,cert_rsa_sha512,cert_missing_key_returns_agent_failure,missing_key_returns_agent_failure}), PKCS#8 / OpenSSH key decoding (test_decode_pkcs8_p{256,384,521}_secret_key, test_decode_ed25519_{,aesctr}_secret_key, test_pkcs8_encrypted, format::test_ec_private_key), channel lifecycle (channels::test_{channel_objects,channel_streams,server_channels,channel_window_size,server_receives_close_on_client_close}), and protocol-level paths (gex::peer_request_accepts_rfc4419_minimum_when_server_can_choose_stronger_group, gex::local_client_config_still_rejects_minimum_below_2048, compress::compress_local_test, future_certificate::test_future_certificate_auth_full_flow, server_kex_junk::server_kex_junk_test). Full workspace aggregate is now 1871 passed / 0 failed / 10 ignored, up from 1796 on PR #203 because the 75 newly-runnable bssh-russh tests are now contributing. Note: `cargo clippy --workspace --tests -- -D warnings` does report ~250 warnings on the newly-reachable test code (mostly `clippy::panic` on `panic!("Unexpected message ...")` arms and similar idioms that upstream russh writes routinely in their test scaffolding). They are inherited verbatim from upstream and don't affect runtime behavior; cleaning them up is a separate follow-up so this PR can stay focused on unblocking the test target.
4 tasks
inureyes
added a commit
that referenced
this pull request
May 18, 2026
) CI on rustc 1.95 fails `cargo clippy -- -D warnings` with `clippy::useless_conversion` on `client/session.rs:194` because `Iterator::chain` already accepts any `IntoIterator`, so the explicit `.chain(files.into_iter())` is redundant. The lint did not exist (or was less aggressive) on rustc 1.93 where PR #203 was developed, so the issue only surfaced after upstream toolchain bump. The line was imported verbatim from upstream russh-sftp 2.1.2 when we full-source-synced the fork in PR #203. Upstream has the same lint waiting to fire whenever they bump their MSRV / clippy. Fix is the obvious one — `.chain(files)` instead of `.chain(files.into_iter())`. Functionally identical, just lets the trait do its job. Verified locally on rustc 1.95.0 (matching CI): `cargo clippy -- -D warnings` clean, `cargo clippy --workspace --lib -- -D warnings` clean, `cargo test --lib` 1233 passed / 0 failed / 9 ignored (matches CI's `cargo test --lib --verbose` step exactly). No other `useless_conversion` hits in the workspace's lib targets under 1.95. The same change is worth filing upstream against AspectUnk/russh-sftp so future syncs don't have to re-port this; tracking that as a follow-up rather than blocking this CI fix.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Workspace-wide dependency upgrade pass plus a controlled sync of both internal russh forks to upstream stable, picking up
CVE-2026-46673in the process.Main bssh crate
lru0.17.0 → 0.18.0 (lifetime fix inget_or_insert_mut_ref; no API surface change for our LRU usage insrc/ssh/config_cache/manager.rs).signal-hook0.3 → 0.4 (the only breaking change islow_level::pipewhich we don't use;consts::SIGWINCHanditerator::Signalsare stable across the bump).opentelemetry/opentelemetry_sdk/opentelemetry-otlp0.31 → 0.32 (the removedExportConfig/HasExportConfigtrio isn't called from oursrc/server/audit/otel.rs;WithExportConfig::with_endpoint,LogExporter::builder().with_tonic(),SdkLoggerProvider::builder(),Resource::builder(), and theLogRecordAPI all remain source-compatible). Note: 0.32 now errors when anhttps://endpoint is configured without a TLS feature; our current features stay at[grpc-tonic, logs]because all uses today arehttp://— a follow-up will be needed if anyone runs the audit exporter against TLS in production.nix0.31.2 → 0.31.3 plus transitive bumps inpin-project,tower-http, andzerofromviacargo update.bssh-russh fork: 0.60.1 → 0.60.3
russh-cryptovec0.59.0 → 0.60.3 andaws-lc-rs1.16.3 → 1.17.0. The cryptovec bump carries theCryptoVechardening half ofCVE-2026-46673(compression ZIP-bomb DoS).CVE-2026-46673(upstream commita2d48a7) intosrc/keys/agent/{client,server}.rssince stable v0.60.3 includes it but our fork was based on 0.60.1 and did not. AddsMAX_AGENT_FRAME_LEN = 256 * 1024, factors outread_frame(), and rejects oversized peer frame lengths withError::AgentProtocolErrorbefore resizing the receive buffer. The same change is recorded ascrates/bssh-russh/patches/agent-frame-length-cap.patchsosync-upstream.sh's reverse-apply dry-run will auto-skip it on the next sync.#690SHA-1 MAC exclusion,#693channel write ordering), so no double-apply.bssh-russh-sftp fork: 2.1.1 → 2.1.2
russh-sftp2.1.2 (src/replaced by upstream tree). Upstream 2.1.2 absorbed the originalserde_bytesperf fix onprotocol::Write.dataandprotocol::Data.dataplus the matchingserialize_bytesimplementation, sopatches/sftp-serde-bytes-perf.patchis moved topatches/historical/for provenance.FileI/O helpers,write_all_pipelined(&mut reader, max_inflight)andread_to_writer_pipelined(&mut writer, max_inflight). These drivereader → fileandfile → writertransfers with bounded in-flight chunks to hide per-request RTT, mirroring how OpenSSH'ssftpclient keeps ~64 outstanding requests by default. They were undocumented in the previous Cargo.toml description (only the perf patch was mentioned), which almost caused them to be lost when this PR initially tried to drop the fork. They are now re-ported on top of upstream 2.1.2's newFeaturesAPI: chunk size derives fromfeatures.limits.{write,read}_lenor, when unadvertised, fromfeatures.max_packet_len.saturating_sub({WRITE,READ}_OVERHEAD_LENGTH)instead of the removedMAX_*_LENGTHconstants.crates/bssh-russh-sftp/Cargo.tomlreplacesflurrywithdashmap 6.1.0, addsserde_bytesas a direct dep, keepsfutures(used by our pipelined helpers'FuturesUnordered), pins versions to upstream's set, and updates the package description to call out both the absorbed perf fix and the still-custom pipelined helpers — so the next maintainer doesn't repeat the near-miss of deleting the fork without realizing the pipelined methods aren't in upstream.Security
CVE-2026-46673is closed for the SSH-agent peer path by the forward-ported frame-length cap, and for the cryptovec path by therussh-cryptovec 0.60.3bump.cargo auditagainst the latest 1090-advisory RustSec database reports 0 vulnerabilities and 0 unmaintained/yanked warnings after the upgrade.What is not bumped
The remaining "outdated" direct deps in
bssh-russh(aes 0.9,hmac 0.13,sha1/sha20.11,digest0.11,cbc/ctr/desnew majors,pkcs5/pkcs8stable, and the RC familyecdsa rc.18/rsa rc.18/elliptic-curve rc.32/ed25519-dalek pre.7) are blocked by RustCrypto's coordinated release model — they share trait crates, and the pre-release crypto crates we depend on still require the old trait versions. Upstream russh stable v0.60.3 carries the same constraints, so we deliberately stay aligned with it. Transitivelru@0.16.4andsignal-hook@0.3.18are pulled in byratatui-core/crosstermrespectively and will resolve themselves whenever those upstream crates bump.Test plan
cargo build— cleancargo check --all-targets— cleancargo clippy -p bssh --bins -p bssh-russh-sftp --lib -- -D warnings— cleancargo fmt— appliedcargo test --lib server::audit::otel— 5 pass / 2 ignored (require a live OTLP collector)cargo test --lib ssh::config_cache— 14 passcargo test --lib pty::— 195 passcargo test -p bssh --lib ssh::— 280 passcargo audit— 0 vulnerabilities, 0 warnings against 1090-advisory DB