From 5c5fc613602898de4423b79a36a0e704fe5513aa Mon Sep 17 00:00:00 2001 From: adiraj66132 Date: Sun, 12 Jul 2026 03:09:24 +0530 Subject: [PATCH 1/3] Verify SFTP host keys --- yazi-vfs/src/provider/sftp/conn.rs | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/yazi-vfs/src/provider/sftp/conn.rs b/yazi-vfs/src/provider/sftp/conn.rs index 413f41db..1b35cdcd 100644 --- a/yazi-vfs/src/provider/sftp/conn.rs +++ b/yazi-vfs/src/provider/sftp/conn.rs @@ -1,8 +1,8 @@ use std::{io, sync::Arc, time::{Duration, SystemTime}}; use chrono::DateTime; -use russh::keys::{PrivateKeyWithHashAlg, agent::AgentIdentity}; -use yazi_fs::provider::local::Local; +use russh::keys::{PrivateKeyWithHashAlg, agent::AgentIdentity, known_hosts}; +use yazi_fs::{provider::local::Local, Xdg}; use crate::config::ServiceSftp; @@ -23,9 +23,30 @@ impl russh::client::Handler for Conn { async fn check_server_key( &mut self, - _server_public_key: &russh::keys::PublicKey, + server_public_key: &russh::keys::PublicKey, ) -> Result { - Ok(true) + let path = Xdg::config_dir().join("known_hosts"); + + match known_hosts::check_known_hosts_path(&self.config.host, self.config.port, server_public_key, &path) { + Ok(true) => Ok(true), + Ok(false) => { + if let Err(e) = known_hosts::learn_known_hosts_path(&self.config.host, self.config.port, server_public_key, &path) { + tracing::warn!("Failed to record host key in known_hosts: {e}"); + } + Ok(true) + } + Err(russh::keys::Error::KeyChanged { line }) => { + tracing::error!( + "Host key for `{}` has changed (known_hosts:{}). Possible MITM attack!", + self.config.host, line + ); + Ok(false) + } + Err(e) => { + tracing::warn!("Could not verify host key for `{}`: {e}", self.config.host); + Ok(true) + } + } } } From 816e221bf54443b585de9a37ee63348dee2eee5b Mon Sep 17 00:00:00 2001 From: adiraj66132 Date: Sun, 12 Jul 2026 03:27:13 +0530 Subject: [PATCH 2/3] Format code with rustfmt --- yazi-vfs/src/provider/sftp/conn.rs | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/yazi-vfs/src/provider/sftp/conn.rs b/yazi-vfs/src/provider/sftp/conn.rs index 1b35cdcd..0472cd2a 100644 --- a/yazi-vfs/src/provider/sftp/conn.rs +++ b/yazi-vfs/src/provider/sftp/conn.rs @@ -2,7 +2,7 @@ use std::{io, sync::Arc, time::{Duration, SystemTime}}; use chrono::DateTime; use russh::keys::{PrivateKeyWithHashAlg, agent::AgentIdentity, known_hosts}; -use yazi_fs::{provider::local::Local, Xdg}; +use yazi_fs::{Xdg, provider::local::Local}; use crate::config::ServiceSftp; @@ -27,10 +27,20 @@ impl russh::client::Handler for Conn { ) -> Result { let path = Xdg::config_dir().join("known_hosts"); - match known_hosts::check_known_hosts_path(&self.config.host, self.config.port, server_public_key, &path) { + match known_hosts::check_known_hosts_path( + &self.config.host, + self.config.port, + server_public_key, + &path, + ) { Ok(true) => Ok(true), Ok(false) => { - if let Err(e) = known_hosts::learn_known_hosts_path(&self.config.host, self.config.port, server_public_key, &path) { + if let Err(e) = known_hosts::learn_known_hosts_path( + &self.config.host, + self.config.port, + server_public_key, + &path, + ) { tracing::warn!("Failed to record host key in known_hosts: {e}"); } Ok(true) @@ -38,7 +48,8 @@ impl russh::client::Handler for Conn { Err(russh::keys::Error::KeyChanged { line }) => { tracing::error!( "Host key for `{}` has changed (known_hosts:{}). Possible MITM attack!", - self.config.host, line + self.config.host, + line ); Ok(false) } From f94b474364b7aeb7c9afec8aa30dbb9b48fcdefe Mon Sep 17 00:00:00 2001 From: adiraj66132 Date: Sun, 12 Jul 2026 10:56:08 +0530 Subject: [PATCH 3/3] fix: reject SFTP connection on host key verification error and panic on SFTP URL rebase - `check_server_key` now rejects (rather than silently accepting) when known_hosts cannot be read or parsed, so a corrupt/unreadable file no longer disables host-key verification. - `UrlBuf::rebase` no longer hits `todo!()` for SFTP URLs; it rebases via a typed `UnixPath` base, matching the other URL variants. --- yazi-shared/src/url/buf.rs | 4 ++-- yazi-vfs/src/provider/sftp/conn.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yazi-shared/src/url/buf.rs b/yazi-shared/src/url/buf.rs index ef9b2e05..cfdb80de 100644 --- a/yazi-shared/src/url/buf.rs +++ b/yazi-shared/src/url/buf.rs @@ -167,8 +167,8 @@ impl UrlBuf { Self::Archive { loc: loc.rebase(base), domain: domain.clone() } } Self::Sftp { loc, domain } => { - todo!(); - // Self::Sftp { loc: loc.rebase(base), domain: domain.clone() } + let base = typed_path::UnixPath::new(base.as_os_str().as_encoded_bytes()); + Self::Sftp { loc: loc.rebase(base), domain: domain.clone() } } } } diff --git a/yazi-vfs/src/provider/sftp/conn.rs b/yazi-vfs/src/provider/sftp/conn.rs index 0472cd2a..7f95fbf0 100644 --- a/yazi-vfs/src/provider/sftp/conn.rs +++ b/yazi-vfs/src/provider/sftp/conn.rs @@ -54,8 +54,8 @@ impl russh::client::Handler for Conn { Ok(false) } Err(e) => { - tracing::warn!("Could not verify host key for `{}`: {e}", self.config.host); - Ok(true) + tracing::error!("Could not verify host key for `{}`: {e}", self.config.host); + Ok(false) } } }