1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

Configure clippy (#16194)

Apply the same clippy configuration as we have in sdk-internal. bitwarden/sdk-internal@49f84e6/Cargo.toml#L91-L94

Adds FIXME comments to all existing violations. unwrap is bad as those will resullt in panics and crash the application. Unused async is ignored in napi since that would require changes to the js side which I don't want to deal with.
This commit is contained in:
Oscar Hinton
2025-08-29 14:27:50 +02:00
committed by GitHub
parent 2b2912b1be
commit 97ee61db00
27 changed files with 131 additions and 37 deletions

View File

@@ -102,3 +102,10 @@ jobs:
run: cargo clippy --all-features --tests
env:
RUSTFLAGS: "-D warnings"
- name: Install cargo-sort
run: cargo install cargo-sort --locked --git https://github.com/DevinR528/cargo-sort.git --rev f5047967021cbb1f822faddc355b3b07674305a1
- name: Cargo sort
working-directory: ./apps/desktop/desktop_native
run: cargo sort --workspace --check

View File

@@ -1,6 +1,13 @@
[workspace]
resolver = "2"
members = ["napi", "core", "proxy", "macos_provider", "windows_plugin_authenticator", "autotype"]
members = [
"autotype",
"core",
"macos_provider",
"napi",
"proxy",
"windows_plugin_authenticator"
]
[workspace.package]
version = "0.0.0"
@@ -21,7 +28,7 @@ bytes = "=1.10.1"
cbc = "=0.1.2"
core-foundation = "=0.10.0"
dirs = "=6.0.0"
ed25519 = "=2.2.3"
ed25519 = "=2.2.3"
embed_plist = "=1.2.2"
futures = "=0.3.31"
hex = "=0.4.3"
@@ -36,7 +43,7 @@ napi-derive = "=2.16.13"
oo7 = "=0.4.3"
oslog = "=0.2.0"
pin-project = "=1.1.10"
pkcs8 = "=0.10.2"
pkcs8 = "=0.10.2"
rand = "=0.9.1"
rsa = "=0.9.6"
russh-cryptovec = "=0.7.3"
@@ -48,14 +55,14 @@ serde_json = "=1.0.127"
sha2 = "=0.10.8"
simplelog = "=0.12.2"
ssh-encoding = "=0.2.0"
ssh-key = {version = "=0.6.7", default-features = false }
ssh-key = { version = "=0.6.7", default-features = false }
sysinfo = "=0.35.0"
thiserror = "=2.0.12"
tokio = "=1.45.0"
tokio-stream = "=0.1.15"
tokio-util = "=0.7.13"
typenum = "=1.18.0"
uniffi = "=0.28.3"
uniffi = "=0.28.3"
widestring = "=1.2.0"
windows = "=0.61.1"
windows-core = "=0.61.0"
@@ -64,3 +71,8 @@ windows-registry = "=0.5.3"
zbus = "=5.5.0"
zbus_polkit = "=5.0.0"
zeroizing-alloc = "=0.1.0"
[workspace.lints.clippy]
unused_async = "deny"
unwrap_used = "deny"
string_slice = "warn"

View File

@@ -6,5 +6,11 @@ edition.workspace = true
publish.workspace = true
[target.'cfg(windows)'.dependencies]
windows = { workspace = true, features = ["Win32_UI_Input_KeyboardAndMouse", "Win32_UI_WindowsAndMessaging"] }
windows = { workspace = true, features = [
"Win32_UI_Input_KeyboardAndMouse",
"Win32_UI_WindowsAndMessaging",
] }
windows-core = { workspace = true }
[lints]
workspace = true

View File

@@ -0,0 +1,2 @@
allow-unwrap-in-tests=true
allow-expect-in-tests=true

View File

@@ -7,32 +7,35 @@ publish = { workspace = true }
[features]
default = [
"dep:widestring",
"dep:windows",
"dep:core-foundation",
"dep:security-framework",
"dep:security-framework-sys",
"dep:zbus",
"dep:zbus_polkit",
"dep:widestring",
"dep:windows",
"dep:core-foundation",
"dep:security-framework",
"dep:security-framework-sys",
"dep:zbus",
"dep:zbus_polkit"
]
manual_test = []
[dependencies]
aes = { workspace = true }
anyhow = { workspace = true }
arboard = { workspace = true, features = [
"wayland-data-control",
] }
arboard = { workspace = true, features = ["wayland-data-control"] }
base64 = { workspace = true }
bitwarden-russh = { workspace = true }
byteorder = { workspace = true }
bytes = { workspace = true }
cbc = { workspace = true, features = ["alloc"] }
homedir = { workspace = true }
pin-project = { workspace = true }
dirs = { workspace = true }
ed25519 = { workspace = true, features = ["pkcs8"] }
futures = { workspace = true }
homedir = { workspace = true }
interprocess = { workspace = true, features = ["tokio"] }
log = { workspace = true }
pin-project = { workspace = true }
pkcs8 = { workspace = true, features = ["alloc", "encryption", "pem"] }
rand = { workspace = true }
rsa = { workspace = true }
russh-cryptovec = { workspace = true }
scopeguard = { workspace = true }
sha2 = { workspace = true }
@@ -43,17 +46,12 @@ ssh-key = { workspace = true, features = [
"rsa",
"getrandom",
] }
bitwarden-russh = { workspace = true }
sysinfo = { workspace = true, features = ["windows"] }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["io-util", "sync", "macros", "net"] }
tokio-stream = { workspace = true, features = ["net"] }
tokio-util = { workspace = true, features = ["codec"] }
thiserror = { workspace = true }
typenum = { workspace = true }
pkcs8 = { workspace = true, features = ["alloc", "encryption", "pem"] }
rsa = { workspace = true }
ed25519 = { workspace = true, features = ["pkcs8"] }
bytes = { workspace = true }
sysinfo = { workspace = true, features = ["windows"] }
zeroizing-alloc = { workspace = true }
[target.'cfg(windows)'.dependencies]
@@ -88,3 +86,6 @@ ashpd = { workspace = true }
zbus = { workspace = true, optional = true }
zbus_polkit = { workspace = true, optional = true }
[lints]
workspace = true

View File

@@ -1,5 +1,6 @@
use anyhow::Result;
#[allow(clippy::unused_async)]
pub async fn run_command(_value: String) -> Result<String> {
todo!("Unix does not support autofill");
}

View File

@@ -1,5 +1,6 @@
use anyhow::Result;
#[allow(clippy::unused_async)]
pub async fn run_command(_value: String) -> Result<String> {
todo!("Windows does not support autofill");
}

View File

@@ -1,5 +1,6 @@
use anyhow::Result;
#[allow(clippy::unused_async)]
pub async fn set_autostart(_autostart: bool, _params: Vec<String>) -> Result<()> {
unimplemented!();
}

View File

@@ -27,6 +27,8 @@ use super::{decrypt, encrypt, windows_focus::set_focus};
pub struct Biometric {}
impl super::BiometricTrait for Biometric {
// FIXME: Remove unwraps! They panic and terminate the whole application.
#[allow(clippy::unwrap_used)]
async fn prompt(hwnd: Vec<u8>, message: String) -> Result<bool> {
let h = isize::from_le_bytes(hwnd.clone().try_into().unwrap());

View File

@@ -30,6 +30,8 @@ fn internal_ipc_codec<T: AsyncRead + AsyncWrite>(inner: T) -> Framed<T, LengthDe
}
/// Resolve the path to the IPC socket.
// FIXME: Remove unwraps! They panic and terminate the whole application.
#[allow(clippy::unwrap_used)]
pub fn path(name: &str) -> std::path::PathBuf {
#[cfg(target_os = "windows")]
{

View File

@@ -4,22 +4,26 @@ use security_framework::passwords::{
delete_generic_password, get_generic_password, set_generic_password,
};
#[allow(clippy::unused_async)]
pub async fn get_password(service: &str, account: &str) -> Result<String> {
let password = get_generic_password(service, account).map_err(convert_error)?;
let result = String::from_utf8(password)?;
Ok(result)
}
#[allow(clippy::unused_async)]
pub async fn set_password(service: &str, account: &str, password: &str) -> Result<()> {
set_generic_password(service, account, password.as_bytes())?;
Ok(())
}
#[allow(clippy::unused_async)]
pub async fn delete_password(service: &str, account: &str) -> Result<()> {
delete_generic_password(service, account).map_err(convert_error)?;
Ok(())
}
#[allow(clippy::unused_async)]
pub async fn is_available() -> Result<bool> {
Ok(true)
}

View File

@@ -14,6 +14,7 @@ use windows::{
const CRED_FLAGS_NONE: u32 = 0;
#[allow(clippy::unused_async)]
pub async fn get_password(service: &str, account: &str) -> Result<String> {
let target_name = U16CString::from_str(target_name(service, account))?;
@@ -46,6 +47,7 @@ pub async fn get_password(service: &str, account: &str) -> Result<String> {
Ok(password)
}
#[allow(clippy::unused_async)]
pub async fn set_password(service: &str, account: &str, password: &str) -> Result<()> {
let mut target_name = U16CString::from_str(target_name(service, account))?;
let mut user_name = U16CString::from_str(account)?;
@@ -77,6 +79,7 @@ pub async fn set_password(service: &str, account: &str, password: &str) -> Resul
Ok(())
}
#[allow(clippy::unused_async)]
pub async fn delete_password(service: &str, account: &str) -> Result<()> {
let target_name = U16CString::from_str(target_name(service, account))?;
@@ -87,6 +90,7 @@ pub async fn delete_password(service: &str, account: &str) -> Result<()> {
Ok(())
}
#[allow(clippy::unused_async)]
pub async fn is_available() -> Result<bool> {
Ok(true)
}

View File

@@ -19,6 +19,8 @@ const SCREEN_LOCK_MONITORS: [ScreenLock; 2] = [
},
];
// FIXME: Remove unwraps! They panic and terminate the whole application.
#[allow(clippy::unwrap_used)]
pub async fn on_lock(tx: tokio::sync::mpsc::Sender<()>) -> Result<(), Box<dyn std::error::Error>> {
let connection = Connection::session().await?;
@@ -41,6 +43,8 @@ pub async fn on_lock(tx: tokio::sync::mpsc::Sender<()>) -> Result<(), Box<dyn st
Ok(())
}
// FIXME: Remove unwraps! They panic and terminate the whole application.
#[allow(clippy::unwrap_used)]
pub async fn is_lock_monitor_available() -> bool {
let connection = Connection::session().await.unwrap();
for monitor in SCREEN_LOCK_MONITORS {

View File

@@ -1,7 +1,9 @@
#[allow(clippy::unused_async)]
pub async fn on_lock(_: tokio::sync::mpsc::Sender<()>) -> Result<(), Box<dyn std::error::Error>> {
unimplemented!();
}
#[allow(clippy::unused_async)]
pub async fn is_lock_monitor_available() -> bool {
false
}

View File

@@ -90,7 +90,7 @@ impl ssh_agent::Agent<peerinfo::models::PeerInfo, BitwardenSshKey>
return false;
}
let request_id = self.get_request_id().await;
let request_id = self.get_request_id();
let request_data = match request_parser::parse_request(data) {
Ok(data) => data,
Err(e) => {
@@ -138,7 +138,7 @@ impl ssh_agent::Agent<peerinfo::models::PeerInfo, BitwardenSshKey>
return true;
}
let request_id = self.get_request_id().await;
let request_id = self.get_request_id();
let mut rx_channel = self.get_ui_response_rx.lock().await.resubscribe();
let message = SshAgentUIRequest {
@@ -263,7 +263,7 @@ impl BitwardenDesktopAgent<BitwardenSshKey> {
Ok(())
}
async fn get_request_id(&self) -> u32 {
fn get_request_id(&self) -> u32 {
if !self.is_running() {
println!("[BitwardenDesktopAgent] Agent is not running, but tried to get request id");
return 0;

View File

@@ -26,6 +26,8 @@ pub struct NamedPipeServerStream {
}
impl NamedPipeServerStream {
// FIXME: Remove unwraps! They panic and terminate the whole application.
#[allow(clippy::unwrap_used)]
pub fn new(cancellation_token: CancellationToken, is_running: Arc<AtomicBool>) -> Self {
let (tx, rx) = tokio::sync::mpsc::channel(16);
tokio::spawn(async move {

View File

@@ -18,7 +18,7 @@ use crate::ssh_agent::peercred_unix_listener_stream::PeercredUnixListenerStream;
use super::{BitwardenDesktopAgent, BitwardenSshKey, SshAgentUIRequest};
impl BitwardenDesktopAgent<BitwardenSshKey> {
pub async fn start_server(
pub fn start_server(
auth_request_tx: tokio::sync::mpsc::Sender<SshAgentUIRequest>,
auth_response_rx: Arc<Mutex<tokio::sync::broadcast::Receiver<(u32, bool)>>>,
) -> Result<Self, anyhow::Error> {

View File

@@ -14,7 +14,7 @@ use tokio_util::sync::CancellationToken;
use super::{BitwardenDesktopAgent, BitwardenSshKey, SshAgentUIRequest};
impl BitwardenDesktopAgent<BitwardenSshKey> {
pub async fn start_server(
pub fn start_server(
auth_request_tx: tokio::sync::mpsc::Sender<SshAgentUIRequest>,
auth_response_rx: Arc<Mutex<tokio::sync::broadcast::Receiver<(u32, bool)>>>,
) -> Result<Self, anyhow::Error> {

View File

@@ -28,3 +28,6 @@ oslog = { workspace = true }
[build-dependencies]
uniffi = { workspace = true, features = ["build"] }
[lints]
workspace = true

View File

@@ -61,6 +61,8 @@ pub struct MacOSProviderClient {
#[uniffi::export]
impl MacOSProviderClient {
// FIXME: Remove unwraps! They panic and terminate the whole application.
#[allow(clippy::unwrap_used)]
#[uniffi::constructor]
pub fn connect() -> Self {
let _ = oslog::OsLogger::new("com.bitwarden.desktop.autofill-extension")
@@ -179,6 +181,8 @@ enum SerializedMessage {
}
impl MacOSProviderClient {
// FIXME: Remove unwraps! They panic and terminate the whole application.
#[allow(clippy::unwrap_used)]
fn add_callback(&self, callback: Box<dyn Callback>) -> u32 {
let sequence_number = self
.response_callbacks_counter
@@ -192,6 +196,8 @@ impl MacOSProviderClient {
sequence_number
}
// FIXME: Remove unwraps! They panic and terminate the whole application.
#[allow(clippy::unwrap_used)]
fn send_message(
&self,
message: impl Serialize + DeserializeOwned,

View File

@@ -14,19 +14,19 @@ default = []
manual_test = []
[dependencies]
anyhow = { workspace = true }
autotype = { path = "../autotype" }
base64 = { workspace = true }
hex = { workspace = true }
anyhow = { workspace = true }
desktop_core = { path = "../core" }
hex = { workspace = true }
log = { workspace = true }
napi = { workspace = true, features = ["async"] }
napi-derive = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
tokio = { workspace = true }
tokio-util = { workspace = true }
tokio-stream = { workspace = true }
tokio-util = { workspace = true }
[target.'cfg(windows)'.dependencies]
windows-registry = { workspace = true }
@@ -34,3 +34,6 @@ windows_plugin_authenticator = { path = "../windows_plugin_authenticator" }
[build-dependencies]
napi-build = { workspace = true }
[lints]
workspace = true

View File

@@ -110,6 +110,7 @@ pub mod biometrics {
/// If the iv is provided, it will be used as the challenge. Otherwise a random challenge will be generated.
///
/// `format!("<key_base64>|<iv_base64>")`
#[allow(clippy::unused_async)] // FIXME: Remove unused async!
#[napi]
pub async fn derive_key_material(iv: Option<String>) -> napi::Result<OsDerivedKey> {
Biometric::derive_key_material(iv.as_deref())
@@ -150,11 +151,13 @@ pub mod biometrics {
#[napi]
pub mod clipboards {
#[allow(clippy::unused_async)] // FIXME: Remove unused async!
#[napi]
pub async fn read() -> napi::Result<String> {
desktop_core::clipboard::read().map_err(|e| napi::Error::from_reason(e.to_string()))
}
#[allow(clippy::unused_async)] // FIXME: Remove unused async!
#[napi]
pub async fn write(text: String, password: bool) -> napi::Result<()> {
desktop_core::clipboard::write(&text, password)
@@ -201,6 +204,7 @@ pub mod sshagent {
pub namespace: Option<String>,
}
#[allow(clippy::unused_async)] // FIXME: Remove unused async!
#[napi]
pub async fn serve(
callback: ThreadsafeFunction<SshUIRequest, CalleeHandled>,
@@ -262,9 +266,7 @@ pub mod sshagent {
match desktop_core::ssh_agent::BitwardenDesktopAgent::start_server(
auth_request_tx,
Arc::new(Mutex::new(auth_response_rx)),
)
.await
{
) {
Ok(state) => Ok(SshAgentState { state }),
Err(e) => Err(napi::Error::from_reason(e.to_string())),
}
@@ -319,16 +321,21 @@ pub mod sshagent {
#[napi]
pub mod processisolations {
#[allow(clippy::unused_async)] // FIXME: Remove unused async!
#[napi]
pub async fn disable_coredumps() -> napi::Result<()> {
desktop_core::process_isolation::disable_coredumps()
.map_err(|e| napi::Error::from_reason(e.to_string()))
}
#[allow(clippy::unused_async)] // FIXME: Remove unused async!
#[napi]
pub async fn is_core_dumping_disabled() -> napi::Result<bool> {
desktop_core::process_isolation::is_core_dumping_disabled()
.map_err(|e| napi::Error::from_reason(e.to_string()))
}
#[allow(clippy::unused_async)] // FIXME: Remove unused async!
#[napi]
pub async fn disable_memory_access() -> napi::Result<()> {
desktop_core::process_isolation::disable_memory_access()
@@ -367,12 +374,14 @@ pub mod powermonitors {
#[napi]
pub mod windows_registry {
#[allow(clippy::unused_async)] // FIXME: Remove unused async!
#[napi]
pub async fn create_key(key: String, subkey: String, value: String) -> napi::Result<()> {
crate::registry::create_key(&key, &subkey, &value)
.map_err(|e| napi::Error::from_reason(e.to_string()))
}
#[allow(clippy::unused_async)] // FIXME: Remove unused async!
#[napi]
pub async fn delete_key(key: String, subkey: String) -> napi::Result<()> {
crate::registry::delete_key(&key, &subkey)
@@ -432,6 +441,7 @@ pub mod ipc {
///
/// @param name The endpoint name to listen on. This name uniquely identifies the IPC connection and must be the same for both the server and client.
/// @param callback This function will be called whenever a message is received from a client.
#[allow(clippy::unused_async)] // FIXME: Remove unused async!
#[napi(factory)]
pub async fn listen(
name: String,
@@ -609,12 +619,15 @@ pub mod autofill {
server: desktop_core::ipc::server::Server,
}
// FIXME: Remove unwraps! They panic and terminate the whole application.
#[allow(clippy::unwrap_used)]
#[napi]
impl IpcServer {
/// Create and start the IPC server without blocking.
///
/// @param name The endpoint name to listen on. This name uniquely identifies the IPC connection and must be the same for both the server and client.
/// @param callback This function will be called whenever a message is received from a client.
#[allow(clippy::unused_async)] // FIXME: Remove unused async!
#[napi(factory)]
pub async fn listen(
name: String,

View File

@@ -19,3 +19,6 @@ core-foundation = "=0.10.0"
[build-dependencies]
cc = "=1.2.4"
glob = "=0.3.2"
[lints]
workspace = true

View File

@@ -16,3 +16,6 @@ tokio-util = { workspace = true, features = ["codec"] }
[target.'cfg(target_os = "macos")'.dependencies]
embed_plist = { workspace = true }
[lints]
workspace = true

View File

@@ -50,6 +50,8 @@ fn init_logging(log_path: &Path, console_level: LevelFilter, file_level: LevelFi
///
/// Browser extension <-[native messaging]-> proxy <-[ipc]-> desktop
///
// FIXME: Remove unwraps! They panic and terminate the whole application.
#[allow(clippy::unwrap_used)]
#[tokio::main(flavor = "current_thread")]
async fn main() {
#[cfg(target_os = "windows")]

View File

@@ -6,6 +6,14 @@ license = { workspace = true }
publish = { workspace = true }
[target.'cfg(windows)'.dependencies]
windows = { workspace = true, features = ["Win32_Foundation", "Win32_Security", "Win32_System_Com", "Win32_System_LibraryLoader" ] }
windows = { workspace = true, features = [
"Win32_Foundation",
"Win32_Security",
"Win32_System_Com",
"Win32_System_LibraryLoader",
] }
windows-core = { workspace = true }
hex = { workspace = true }
[lints]
workspace = true

View File

@@ -86,6 +86,8 @@ fn register_com_library() -> std::result::Result<(), String> {
}
/// Adds Bitwarden as a plugin authenticator.
// FIXME: Remove unwraps! They panic and terminate the whole application.
#[allow(clippy::unwrap_used)]
fn add_authenticator() -> std::result::Result<(), String> {
let authenticator_name: HSTRING = AUTHENTICATOR_NAME.into();
let authenticator_name_ptr = PCWSTR(authenticator_name.as_ptr()).as_ptr();