VYPR
Low severityOSV Advisory· Published Jan 16, 2026· Updated Jan 16, 2026

RustFS RPC signature verification logs shared secret

CVE-2026-22782

Description

RustFS is a distributed object storage system built in Rust. From >= 1.0.0-alpha.1 to 1.0.0-alpha.79, invalid RPC signatures cause the server to log the shared HMAC secret (and expected signature), which exposes the secret to log readers and enables forged RPC calls. In crates/ecstore/src/rpc/http_auth.rs, the invalid signature branch logs sensitive data. This log line includes secret and expected_signature, both derived from the shared HMAC key. Any invalidly signed request triggers this path. The function is reachable from RPC and admin request handlers. This vulnerability is fixed in 1.0.0-alpha.80.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
rustfscrates.io
>= 1.0.0-alpha.1, < 1.0.0-alpha.801.0.0-alpha.80

Affected products

1
  • Range: 1.0.0-alpha.1, 1.0.0-alpha.10, 1.0.0-alpha.11, …

Patches

1
6b2eebee1d07

fix: Remove secret and signature from the log (#1466)

https://github.com/rustfs/rustfshousemeJan 11, 2026via ghsa
3 files changed · +75 12
  • crates/ecstore/src/rpc/http_auth.rs+8 3 modified
    @@ -108,14 +108,19 @@ pub fn verify_rpc_signature(url: &str, method: &Method, headers: &HeaderMap) ->
         }
     
         // Generate expected signature
    -
         let expected_signature = generate_signature(&secret, url, method, timestamp);
     
         // Compare signatures
         if signature != expected_signature {
             error!(
    -            "verify_rpc_signature: Invalid signature: secret {}, url {}, method {}, timestamp {}, signature {}, expected_signature {}",
    -            secret, url, method, timestamp, signature, expected_signature
    +            "verify_rpc_signature: Invalid signature: url {}, method {}, timestamp {}, signature {}, expected_signature: {}***{}|{}",
    +            url,
    +            method,
    +            timestamp,
    +            signature,
    +            expected_signature.chars().next().unwrap_or('*'),
    +            expected_signature.chars().last().unwrap_or('*'),
    +            expected_signature.len()
             );
     
             return Err(std::io::Error::other("Invalid signature"));
    
  • rustfs/src/admin/mod.rs+0 2 modified
    @@ -239,14 +239,12 @@ pub fn make_admin_route(console_enabled: bool) -> std::io::Result<impl S3Route>
         )?;
     
         // Performance profiling endpoints (available on all platforms, with platform-specific responses)
    -    #[cfg(not(target_os = "windows"))]
         r.insert(
             Method::GET,
             format!("{}{}", ADMIN_PREFIX, "/debug/pprof/profile").as_str(),
             AdminOperation(&handlers::ProfileHandler {}),
         )?;
     
    -    #[cfg(not(target_os = "windows"))]
         r.insert(
             Method::GET,
             format!("{}{}", ADMIN_PREFIX, "/debug/pprof/status").as_str(),
    
  • rustfs/src/config/mod.rs+67 7 modified
    @@ -47,7 +47,7 @@ const LONG_VERSION: &str = concat!(
         concat!("git status   :\n", build::GIT_STATUS_FILE),
     );
     
    -#[derive(Debug, Parser, Clone)]
    +#[derive(Parser, Clone)]
     #[command(version = SHORT_VERSION, long_version = LONG_VERSION)]
     pub struct Opt {
         /// DIR points to a directory on a filesystem.
    @@ -60,7 +60,11 @@ pub struct Opt {
         pub volumes: Vec<String>,
     
         /// bind to a specific ADDRESS:PORT, ADDRESS can be an IP or hostname
    -    #[arg(long, default_value_t = rustfs_config::DEFAULT_ADDRESS.to_string(), env = "RUSTFS_ADDRESS")]
    +    #[arg(
    +        long,
    +        default_value_t = rustfs_config::DEFAULT_ADDRESS.to_string(),
    +        env = "RUSTFS_ADDRESS"
    +    )]
         pub address: String,
     
         /// Domain name used for virtual-hosted-style requests.
    @@ -73,23 +77,43 @@ pub struct Opt {
         pub server_domains: Vec<String>,
     
         /// Access key used for authentication.
    -    #[arg(long, default_value_t = rustfs_credentials::DEFAULT_ACCESS_KEY.to_string(), env = "RUSTFS_ACCESS_KEY")]
    +    #[arg(
    +        long,
    +        default_value_t = rustfs_credentials::DEFAULT_ACCESS_KEY.to_string(),
    +        env = "RUSTFS_ACCESS_KEY"
    +    )]
         pub access_key: String,
     
         /// Secret key used for authentication.
    -    #[arg(long, default_value_t = rustfs_credentials::DEFAULT_SECRET_KEY.to_string(), env = "RUSTFS_SECRET_KEY")]
    +    #[arg(
    +        long,
    +        default_value_t = rustfs_credentials::DEFAULT_SECRET_KEY.to_string(),
    +        env = "RUSTFS_SECRET_KEY"
    +    )]
         pub secret_key: String,
     
         /// Enable console server
    -    #[arg(long, default_value_t = rustfs_config::DEFAULT_CONSOLE_ENABLE, env = "RUSTFS_CONSOLE_ENABLE")]
    +    #[arg(
    +        long,
    +        default_value_t = rustfs_config::DEFAULT_CONSOLE_ENABLE,
    +        env = "RUSTFS_CONSOLE_ENABLE"
    +    )]
         pub console_enable: bool,
     
         /// Console server bind address
    -    #[arg(long, default_value_t = rustfs_config::DEFAULT_CONSOLE_ADDRESS.to_string(), env = "RUSTFS_CONSOLE_ADDRESS")]
    +    #[arg(
    +        long,
    +        default_value_t = rustfs_config::DEFAULT_CONSOLE_ADDRESS.to_string(),
    +        env = "RUSTFS_CONSOLE_ADDRESS"
    +    )]
         pub console_address: String,
     
         /// Observability endpoint for trace, metrics and logs,only support grpc mode.
    -    #[arg(long, default_value_t = rustfs_config::DEFAULT_OBS_ENDPOINT.to_string(), env = "RUSTFS_OBS_ENDPOINT")]
    +    #[arg(
    +        long,
    +        default_value_t = rustfs_config::DEFAULT_OBS_ENDPOINT.to_string(),
    +        env = "RUSTFS_OBS_ENDPOINT"
    +    )]
         pub obs_endpoint: String,
     
         /// tls path for rustfs API and console.
    @@ -137,6 +161,42 @@ pub struct Opt {
         pub buffer_profile: String,
     }
     
    +impl std::fmt::Debug for Opt {
    +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    +        f.debug_struct("Opt")
    +            .field("volumes", &self.volumes)
    +            .field("address", &self.address)
    +            .field("server_domains", &self.server_domains)
    +            .field("access_key", &self.access_key)
    +            .field("secret_key", &Opt::mask_sensitive(Some(&self.secret_key))) // Hide sensitive values
    +            .field("console_enable", &self.console_enable)
    +            .field("console_address", &self.console_address)
    +            .field("obs_endpoint", &self.obs_endpoint)
    +            .field("tls_path", &self.tls_path)
    +            .field("license", &Opt::mask_sensitive(self.license.as_ref()))
    +            .field("region", &self.region)
    +            .field("kms_enable", &self.kms_enable)
    +            .field("kms_backend", &self.kms_backend)
    +            .field("kms_key_dir", &self.kms_key_dir)
    +            .field("kms_vault_address", &self.kms_vault_address)
    +            .field("kms_vault_token", &Opt::mask_sensitive(self.kms_vault_token.as_ref()))
    +            .field("kms_default_key_id", &self.kms_default_key_id)
    +            .field("buffer_profile_disable", &self.buffer_profile_disable)
    +            .field("buffer_profile", &self.buffer_profile)
    +            .finish()
    +    }
    +}
    +
    +impl Opt {
    +    /// Mask sensitive information in Option<String>
    +    fn mask_sensitive(s: Option<&String>) -> String {
    +        match s {
    +            None => "".to_string(),
    +            Some(s) => format!("{}***{}|{}", s.chars().next().unwrap_or('*'), s.chars().last().unwrap_or('*'), s.len()),
    +        }
    +    }
    +}
    +
     // lazy_static::lazy_static! {
     //     pub(crate)  static ref OPT: OnceLock<Opt> = OnceLock::new();
     // }
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.