CVE-2026-22782

RustFS Leak: When Error Logs Become Credentials

Amit Schendel
Amit Schendel
Senior Security Researcher

Jan 17, 2026·5 min read

Executive Summary (TL;DR)

RustFS versions prior to 1.0.0-alpha.80 log the shared HMAC secret when an RPC signature verification fails. This allows attackers with read access to logs to steal the key and gain full control over the storage cluster. The fix involves redacting the secret from error messages.

A classic case of 'debug mode left on in production' affects RustFS, a distributed object storage system. By handling authentication failures too verbosely, the system writes the master HMAC secret directly to the server logs. An attacker with log access—common in modern cloud environments—can retrieve this key and forge valid signatures for any administrative action.

The Hook: Secrets in the stderr

In the world of distributed systems, we often obsess over encryption in transit, encryption at rest, and fancy key management services. We build Fort Knox, install retina scanners, and hire armed guards. Then, just to be helpful, we tape the combination code to the forehead of the guard standing outside.

That is essentially what happened with RustFS, a distributed object storage system built in Rust. In an attempt to make debugging authentication errors easier, the developers inadvertently created a mechanism that dumps the keys to the kingdom straight into the system logs. This isn't a complex heap overflow or a race condition; it's a logic error born of good intentions and bad OpSec.

While the CVSS score sits at a deceptive 'Low' (2.9)—primarily because the attacker needs access to logs—anyone who has worked in a DevOps environment knows that kubectl logs permissions are handed out like candy. If your logs are shipped to ELK, Datadog, or Splunk, that 'Low' severity quickly transforms into a 'Critical' nightmare.

The Flaw: Helping Too Much

The vulnerability lives in crates/ecstore/src/rpc/http_auth.rs, specifically within the signature verification logic. RustFS uses HMAC (Hash-based Message Authentication Code) to verify that Remote Procedure Calls (RPCs) are legitimate. The server calculates an expected_signature using a shared secret and compares it to the incoming request's signature.

So far, so good. But what happens when they don't match? In a secure system, the server should return a generic 401 or 403 error. Maybe log 'Signature verification failed for user X'.

In RustFS, the code decided to be extremely helpful. It thought, "Hey, if the signatures don't match, the developer probably wants to know why." So, it logged everything involved in the calculation. Everything. Including the secret itself. It's the cryptographic equivalent of a bank teller shouting your PIN out loud because you typed it wrong the first time.

The Code: The Smoking Gun

Let's look at the diff. It's rare to see a vulnerability so obvious that it makes you wince physically. Here is the vulnerable logic in verify_rpc_signature:

// The Vulnerable Logic
if signature != expected_signature {
    error!(
        "verify_rpc_signature: Invalid signature: secret {}, url {}, method {}, timestamp {}, signature {}, expected_signature {}",
        secret, // <--- OOPS.
        url, 
        method, 
        timestamp, 
        signature, 
        expected_signature
    );
    return Err(std::io::Error::other("Invalid signature"));
}

The fix, implemented in commit 6b2eebee1d07399ef02c0863bd515b4412a5a560, is straightforward: stop logging the secret. The developers also realized that logging the full expected_signature allows for offline brute-forcing or verification of the secret, so they masked that too.

// The Fix
if signature != expected_signature {
    error!(
        "verify_rpc_signature: Invalid signature: url {}, method {}, timestamp {}, signature {}, expected_signature: {}***{}|{}",
        url,
        method,
        timestamp,
        signature,
        // Masking the expected signature to show only start/end chars
        expected_signature.chars().next().unwrap_or('*'),
        expected_signature.chars().last().unwrap_or('*'),
        expected_signature.len()
    );
    return Err(std::io::Error::other("Invalid signature"));
}

As a bonus, they also caught a similar issue in rustfs/src/config/mod.rs. The configuration struct Opt was using a default #[derive(Debug)]. When the app started up or crashed, it would pretty-print the entire configuration state, including secret_key and kms_vault_token. They replaced this with a manual fmt::Debug implementation that sanitizes these fields.

The Exploit: Asking Nicely for the Password

Exploiting this requires zero coding skill and only basic access privileges (specifically, the ability to read logs). The attack flow is embarrassingly simple:

  1. Poke the Bear: Send a request to the RustFS RPC endpoint with a completely made-up signature. The server tries to verify it, fails, and triggers the error! macro.
  2. Read the Receipt: Open your log aggregator (or docker logs). Look for the string "verify_rpc_signature".
  3. Profit: Copy the plain-text secret from the log entry.

Once the attacker has the HMAC secret, they are effectively a super-admin. They can sign requests to read files, delete volumes, or reconfigure the cluster. The system cannot distinguish them from a legitimate node.

The Impact: Why CVSS 2.9 is a Lie

The CVSS 4.0 score of 2.9 (Low) is technically correct because the vulnerability requires "Attack Requirements: Present" (access to logs). However, in the real world, this score is dangerous. It assumes that logs are treated as highly sensitive data, which is rarely the case.

In modern microservices architectures, logs are often piped to third-party services, viewed by junior developers, or stored in S3 buckets with permissive read policies. If an internal bad actor or a compromised developer account can read logs, they can escalate from "read-only access to logs" to "full read/write access to the storage cluster."

Furthermore, because this is an HMAC secret, it's likely a long-lived static key. Unless the organization has automated secret rotation (unlikely if they are using static HMAC keys), this leaked credential could remain valid for years.

Fix Analysis (1)

Technical Appendix

CVSS Score
2.9/ 10
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:P
EPSS Probability
0.04%
Top 88% most exploited

Affected Systems

RustFS Storage NodesRustFS RPC Interface

Affected Versions Detail

Product
Affected Versions
Fixed Version
RustFS
RustFS
>= 1.0.0-alpha.1, < 1.0.0-alpha.801.0.0-alpha.80
AttributeDetail
CWECWE-532 (Insertion of Sensitive Information into Log File)
Attack VectorNetwork (Trigger) / Local or Network (Log Access)
CVSS 4.02.9 (Low)
ImpactFull System Compromise (via Credential Theft)
Affected Componentcrates/ecstore/src/rpc/http_auth.rs
Exploit ComplexityTrivial
CWE-532
Insertion of Sensitive Information into Log File

The software writes sensitive information to a log file, which can allow an attacker to obtain the information by reading the log.

Vulnerability Timeline

Preliminary Helm chart changes
2026-01-08
Patch committed to master (Commit 6b2eebee1d07399ef02c0863bd515b4412a5a560)
2026-01-11
Vulnerability publicly disclosed (GHSA-333v-68xh-8mmq)
2026-01-16

Subscribe to updates

Get the latest CVE analysis reports delivered to your inbox.