<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>denial-of-service on SecMate Blog</title><link>https://blog.secmate.dev/tags/denial-of-service/</link><description>What we find. What we share.</description><generator>Hugo</generator><language>en-us</language><managingEditor>noreply@blog.secmate.dev//blog.secmate.dev/ (SecMate Team)</managingEditor><lastBuildDate>Tue, 25 Aug 2026 06:06:13 +0000</lastBuildDate><atom:link href="https://blog.secmate.dev/tags/denial-of-service/index.xml" rel="self" type="application/rss+xml"/><item><title>Rust Support in SecMate: Two CVEs in RustFS</title><link>https://blog.secmate.dev/posts/rustfs-vulnerabilities-secmate-rust-support/</link><pubDate>Wed, 04 Feb 2026 12:00:00 +0000</pubDate><dc:creator>Maxime Rossi Bellom</dc:creator><dc:creator>Ramtine Tofighi Shirazi</dc:creator><category>Security</category><category>Vulnerability Research</category><guid>https://blog.secmate.dev/posts/rustfs-vulnerabilities-secmate-rust-support/</guid><description>SecMate's AI-powered static analysis now supports Rust. We demonstrate this with two vulnerabilities in RustFS: an IP-based authentication bypass (CVE-2026-21862) and a remote DoS via gRPC panic (CVE-2025-69255).</description><content:encoded><![CDATA[<h1 id="rust-support-in-secmate-two-cves-in-rustfs">Rust Support in SecMate: Two CVEs in RustFS</h1>
<p>Rust is often praised for its memory safety guarantees, and rightfully so: in safe Rust, buffer overflows, use-after-free, and data races are eliminated at compile time. However, memory safety is not the same as security. Logic bugs, authentication flaws, and improper error handling can still leave Rust applications vulnerable.</p>
<p>To illustrate this, we ran SecMate&rsquo;s automated analysis on RustFS <a href="#ref1">[1]</a>, an S3-compatible object storage server written in Rust. We found two issues: an authentication bypass that lets attackers spoof their IP address to circumvent access controls (CVE-2026-21862 <a href="#ref2">[2]</a>), and a remote denial-of-service caused by unhandled deserialization errors (CVE-2025-69255 <a href="#ref3">[3]</a>).</p>
<h2 id="rust-support-in-secmate">Rust Support in SecMate</h2>
<p><a href="https://secmate.dev?utm_source=blog&amp;utm_medium=body&amp;utm_campaign=rustfs-vulnerabilities-secmate-rust-support&amp;utm_content=security" rel="noopener noreferrer" target="_blank" data-cta-type="body_secmate" data-post-slug="rustfs-vulnerabilities-secmate-rust-support" data-post-category="security">SecMate</a> is an AI-powered static analysis tool specialized in the security of embedded software. We combine static analysis techniques with AI to find vulnerabilities that traditional tools miss: logic bugs, authentication flaws, and subtle design issues that require understanding how data flows through a system.</p>
<p>Rust is increasingly adopted in embedded and systems programming for its memory safety guarantees. Firmware, bootloaders, and security-critical components are being rewritten in Rust to eliminate entire classes of vulnerabilities. To support this trend, we recently added Rust to our analysis engine.</p>
<p>While RustFS is not an embedded application, it made an excellent first target: it is a security-sensitive system handling authentication, access control, and network protocols. This is the kind of complex logic where vulnerabilities hide regardless of the language.</p>
<h2 id="what-is-rustfs">What is RustFS?</h2>
<p>RustFS is an S3-compatible object storage server written in Rust. Think of it as a self-hosted alternative to Amazon S3: you can store and retrieve objects using the same API that countless applications already support.</p>
<p>Key features include:</p>
<ul>
<li>Full S3 API compatibility for drop-in replacement</li>
<li>IAM policies for fine-grained access control</li>
<li>gRPC interface for cluster administration and metrics</li>
<li>Support for erasure coding and distributed deployments</li>
</ul>
<p>RustFS is designed for performance and reliability. It handles sensitive data and access control decisions, making security critical.</p>
<h2 id="vulnerability-1-ip-based-authentication-bypass-cve-2026-21862">Vulnerability #1: IP-Based Authentication Bypass (CVE-2026-21862)</h2>
<p><strong>Location</strong>: <code>rustfs/src/auth.rs:294</code> (<code>get_condition_values</code>)</p>
<h3 id="the-bug">The Bug</h3>
<p>RustFS supports IAM policies that restrict access based on the client&rsquo;s IP address. This is a common pattern: allow operations only from trusted networks, block everything else.</p>
<p>This feature exists because RustFS is often deployed behind a reverse proxy or load balancer. In that setup, every TCP connection appears to come from the proxy, not the real client. To preserve the original client address, proxies add forwarding headers like <code>X-Forwarded-For</code>, and applications use them for both access control and logging. That design only works if the proxy is trusted.</p>
<p>The problem is how RustFS determines the client&rsquo;s IP. It reads forwarding headers like <code>X-Forwarded-For</code> or <code>X-Real-IP</code> and trusts them unconditionally:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="ln">1</span><span class="cl"><span class="kd">let</span><span class="w"> </span><span class="n">remote_addr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">header</span><span class="w">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="w">    </span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#34;x-forwarded-for&#34;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="w">    </span><span class="p">.</span><span class="n">and_then</span><span class="p">(</span><span class="o">|</span><span class="n">v</span><span class="o">|</span><span class="w"> </span><span class="n">v</span><span class="p">.</span><span class="n">to_str</span><span class="p">().</span><span class="n">ok</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="w">    </span><span class="p">.</span><span class="n">and_then</span><span class="p">(</span><span class="o">|</span><span class="n">s</span><span class="o">|</span><span class="w"> </span><span class="n">s</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="sc">&#39;,&#39;</span><span class="p">).</span><span class="n">next</span><span class="p">())</span><span class="w">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="w">    </span><span class="p">.</span><span class="n">or_else</span><span class="p">(</span><span class="o">||</span><span class="w"> </span><span class="n">header</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">&#34;x-real-ip&#34;</span><span class="p">).</span><span class="n">and_then</span><span class="p">(</span><span class="o">|</span><span class="n">v</span><span class="o">|</span><span class="w"> </span><span class="n">v</span><span class="p">.</span><span class="n">to_str</span><span class="p">().</span><span class="n">ok</span><span class="p">()))</span><span class="w">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="w">    </span><span class="p">.</span><span class="n">unwrap_or</span><span class="p">(</span><span class="s">&#34;127.0.0.1&#34;</span><span class="p">);</span><span class="w">
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="w"></span><span class="n">args</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="s">&#34;SourceIp&#34;</span><span class="p">.</span><span class="n">to_owned</span><span class="p">(),</span><span class="w"> </span><span class="fm">vec!</span><span class="p">[</span><span class="n">get_source_ip_raw</span><span class="p">(</span><span class="n">header</span><span class="p">,</span><span class="w"> </span><span class="n">remote_addr</span><span class="p">)]);</span><span class="w">
</span></span></span></code></pre></div><p>RustFS never verifies that the request actually came through a trusted proxy. Any client can set these headers directly.</p>
<h3 id="the-attack">The Attack</h3>
<p>An attacker can bypass IP-based access controls by simply adding a forged header to their request:</p>
<div id="attack-diagram" style="width: 100%; max-width: 680px; margin: 2rem auto; display: block;">
<svg viewBox="0 0 680 380" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Sequence diagram showing IP spoofing attack">
<defs>
<marker id="arrowMain" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#334155"/>
</marker>
<marker id="arrowMainDark" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#e2e8f0"/>
</marker>
<marker id="arrowGreen" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#22c55e"/>
</marker>
</defs>
<!-- Background -->
<rect width="680" height="380" rx="8" class="svg-bg"/>
<!-- Step 0: Actors (visible immediately) -->
<g class="svg-step" data-step="0">
<rect x="40" y="20" width="120" height="50" rx="6" class="svg-attacker-box" stroke-width="2"/>
<text x="100" y="42" text-anchor="middle" class="svg-attacker-text" font-family="system-ui, sans-serif" font-size="14" font-weight="600">Attacker</text>
<text x="100" y="58" text-anchor="middle" class="svg-sub-text" font-family="system-ui, sans-serif" font-size="11">(IP: 1.2.3.4)</text>
<rect x="280" y="20" width="120" height="50" rx="6" class="svg-actor-box" stroke-width="2"/>
<text x="340" y="50" text-anchor="middle" class="svg-actor-text" font-family="system-ui, sans-serif" font-size="14" font-weight="600">RustFS</text>
<rect x="520" y="20" width="120" height="50" rx="6" class="svg-actor-box" stroke-width="2"/>
<text x="580" y="50" text-anchor="middle" class="svg-actor-text" font-family="system-ui, sans-serif" font-size="14" font-weight="600">IAM Policy</text>
<line x1="100" y1="70" x2="100" y2="360" class="svg-lifeline" stroke-width="2" stroke-dasharray="6,4"/>
<line x1="340" y1="70" x2="340" y2="360" class="svg-lifeline" stroke-width="2" stroke-dasharray="6,4"/>
<line x1="580" y1="70" x2="580" y2="360" class="svg-lifeline" stroke-width="2" stroke-dasharray="6,4"/>
</g>
<!-- Step 1: HTTP Request -->
<g class="svg-step" data-step="1">
<line x1="100" y1="110" x2="330" y2="110" class="svg-msg-line svg-arrow-line" stroke-width="2" marker-end="url(#arrowMain)"/>
<text x="215" y="100" text-anchor="middle" class="svg-msg-text" font-family="system-ui, sans-serif" font-size="12">HTTP Request</text>
<text x="215" y="130" text-anchor="middle" class="svg-code-text" font-family="monospace" font-size="11">X-Forwarded-For: 10.0.0.5</text>
</g>
<!-- Step 2: Forged header note -->
<g class="svg-step" data-step="2">
<text x="100" y="160" text-anchor="middle" class="svg-sub-text" font-family="system-ui, sans-serif" font-size="10" font-style="italic">(forged header)</text>
</g>
<!-- Step 3: Policy check -->
<g class="svg-step" data-step="3">
<line x1="340" y1="195" x2="570" y2="195" class="svg-msg-line svg-arrow-line" stroke-width="2" marker-end="url(#arrowMain)"/>
<text x="455" y="185" text-anchor="middle" class="svg-msg-text" font-family="system-ui, sans-serif" font-size="12">Check: is 10.0.0.5 allowed?</text>
</g>
<!-- Step 4: Policy allows -->
<g class="svg-step" data-step="4">
<rect x="500" y="215" width="160" height="35" rx="4" class="svg-policy-box" stroke-width="1"/>
<text x="580" y="237" text-anchor="middle" class="svg-policy-text" font-family="system-ui, sans-serif" font-size="11">Policy allows 10.0.0.5/32</text>
</g>
<!-- Step 5: Allowed response -->
<g class="svg-step" data-step="5">
<line x1="570" y1="275" x2="350" y2="275" stroke="#22c55e" stroke-width="2" stroke-dasharray="6,3" marker-end="url(#arrowGreen)"/>
<text x="460" y="265" text-anchor="middle" class="svg-ok-text" font-family="system-ui, sans-serif" font-size="12" font-weight="600">Allowed</text>
</g>
<!-- Step 6: Access granted -->
<g class="svg-step" data-step="6">
<line x1="330" y1="330" x2="110" y2="330" stroke="#22c55e" stroke-width="2" stroke-dasharray="6,3" marker-end="url(#arrowGreen)"/>
<text x="220" y="320" text-anchor="middle" class="svg-ok-text" font-family="system-ui, sans-serif" font-size="12" font-weight="600">200 OK - Access Granted</text>
</g>
</svg>
</div>
<script>
(function() {
  var diagram = document.getElementById('attack-diagram');
  if (!diagram) return;
  var steps = diagram.querySelectorAll('.svg-step');
  steps.forEach(function(step) {
    if (step.dataset.step !== '0') step.style.opacity = '0';
  });
  var animated = false;
  var observer = new IntersectionObserver(function(entries) {
    entries.forEach(function(entry) {
      if (entry.isIntersecting && !animated) {
        animated = true;
        steps.forEach(function(step) {
          var delay = parseInt(step.dataset.step) * 600;
          setTimeout(function() {
            step.style.transition = 'opacity 0.5s ease-in-out';
            step.style.opacity = '1';
          }, delay);
        });
      }
    });
  }, { threshold: 0.3 });
  observer.observe(diagram);
})();
</script>
<p>Here is what happens step by step:</p>
<ol>
<li>An IAM policy allows <code>s3:ListBucket</code> only from IP <code>10.0.0.5/32</code> (an internal server)</li>
<li>The attacker connects from their external IP <code>1.2.3.4</code></li>
<li>They add the header <code>X-Forwarded-For: 10.0.0.5</code> to their request</li>
<li>RustFS reads the header and believes the client IP is <code>10.0.0.5</code></li>
<li>The IAM policy check passes, and the attacker gets access</li>
</ol>
<h3 id="impact">Impact</h3>
<p>This vulnerability bypasses IP-based access controls when headers are attacker-controlled, such as when clients connect directly to RustFS or through an untrusted proxy. If a trusted proxy controls or strips these headers before forwarding, the risk is reduced. However, in deployments where clients can reach RustFS directly, <code>aws:SourceIp</code> conditions become bypassable. An attacker can:</p>
<ul>
<li>Access buckets restricted to internal networks</li>
<li>Bypass IP allowlists meant for trusted services</li>
<li>Circumvent geographic restrictions</li>
<li>Spoof audit trails and security monitoring by forging client IPs</li>
<li>In the version we analyzed, missing headers fell back to <code>127.0.0.1</code>, so policies allowing localhost could unintentionally allow remote requests</li>
</ul>
<h3 id="fix-status">Fix Status</h3>
<p>This vulnerability has been fixed. RustFS now:</p>
<ul>
<li>Provides an environment variable (<code>_RUSTFS_API_XFF_HEADER</code>) to disable forwarding header processing entirely</li>
<li>Falls back to the actual TCP connection&rsquo;s peer address when headers are missing or disabled</li>
<li>Operators deploying RustFS without a trusted proxy should set <code>_RUSTFS_API_XFF_HEADER=off</code></li>
</ul>
<h2 id="vulnerability-2-remote-dos-via-grpc-panic-cve-2025-69255">Vulnerability #2: Remote DoS via gRPC Panic (CVE-2025-69255)</h2>
<p><strong>Location</strong>: <code>rustfs/src/storage/tonic_service.rs:1768-1785</code> (<code>get_metrics</code>)</p>
<h3 id="the-bug-1">The Bug</h3>
<p>RustFS exposes a gRPC interface for cluster operations, including a <code>GetMetrics</code> endpoint. The handler deserializes client-supplied bytes using <code>Deserialize::deserialize()</code> and calls <code>.unwrap()</code> on the result:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">// In NodeService::get_metrics handler
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"></span><span class="kd">let</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Deserialize</span>::<span class="n">deserialize</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">buf_t</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w">  </span><span class="c1">// Panics on bad input!
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"></span><span class="kd">let</span><span class="w"> </span><span class="n">o</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Deserialize</span>::<span class="n">deserialize</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">buf_o</span><span class="p">).</span><span class="n">unwrap</span><span class="p">();</span><span class="w">  </span><span class="c1">// Same problem here
</span></span></span></code></pre></div><p>In Rust, <code>.unwrap()</code> is convenient for cases where failure is truly unexpected. But here, the input comes from the network. An attacker controls what bytes get deserialized. If they send malformed data, deserialization fails, and <code>.unwrap()</code> triggers a panic, aborting the request.</p>
<p>RustFS does wrap request handling in a panic-catching layer, so a single panic usually returns an error instead of killing the whole process. That limits the blast radius, but panics are still expensive to handle.</p>
<h3 id="the-attack-1">The Attack</h3>
<p>The attack requires sending a malformed gRPC request. When a client sends an empty or invalid <code>metric_type</code> field, the server attempts to deserialize it, fails, and the <code>.unwrap()</code> call causes a panic:</p>
<p>When the malformed request arrives, the server logs a panic:</p>
<pre tabindex="0"><code>thread &#39;rustfs-worker&#39; panicked at rustfs/src/storage/tonic_service.rs:1778:66:
called `Result::unwrap()` on an `Err` value: InvalidMarkerRead(Error {
    kind: UnexpectedEof,
    message: &#34;failed to fill whole buffer&#34;
})
</code></pre><h3 id="impact-1">Impact</h3>
<p>This was a remote denial-of-service risk. The gRPC endpoint uses HMAC signature authentication via <code>x-rustfs-signature</code> and <code>x-rustfs-timestamp</code> headers. A single bad request only affected that one request, but repeated exploitation could cause a real denial-of-service. An attacker with valid credentials could send many malformed requests (or parallelize them across connections) to repeatedly trigger panics, which:</p>
<ul>
<li>Consumed CPU time in panic handling and stack unwinding</li>
<li>Flooded logs with panic traces and slowed down observability pipelines</li>
<li>Starved gRPC worker threads so <code>GetMetrics</code> became effectively unavailable</li>
<li>Could slow other gRPC handlers that share the same runtime under high load</li>
</ul>
<p>The fix was straightforward: replace <code>.unwrap()</code> with proper error handling that returns an error response instead of panicking:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-rust" data-lang="rust"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// Fixed version
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span><span class="kd">let</span><span class="w"> </span><span class="n">t</span>: <span class="nc">MetricType</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">Deserialize</span>::<span class="n">deserialize</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">buf_t</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">    </span><span class="nb">Ok</span><span class="p">(</span><span class="n">t</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">t</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">    </span><span class="nb">Err</span><span class="p">(</span><span class="n">err</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">Response</span>::<span class="n">new</span><span class="p">(</span><span class="n">GetMetricsResponse</span><span class="w"> </span><span class="p">{</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">            </span><span class="n">success</span>: <span class="nc">false</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">            </span><span class="n">error_info</span>: <span class="nb">Some</span><span class="p">(</span><span class="fm">format!</span><span class="p">(</span><span class="s">&#34;Invalid metric_type: </span><span class="si">{err}</span><span class="s">&#34;</span><span class="p">)),</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">            </span><span class="o">..</span><span class="nb">Default</span>::<span class="n">default</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">        </span><span class="p">}));</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">    </span><span class="p">}</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w"></span><span class="p">};</span><span class="w">
</span></span></span></code></pre></div><h3 id="fix-status-1">Fix Status</h3>
<p>This vulnerability has been fixed in current RustFS versions. The <code>.unwrap()</code> calls are gone, and deserialization errors now return a response with <code>success=false</code> and an error string instead of panicking. The fix includes tests to ensure invalid <code>metric_type</code> and <code>opts</code> values do not cause panics.</p>
<h2 id="the-rust-security-reality">The Rust Security Reality</h2>
<p>Both vulnerabilities highlight an important point: <strong>Rust&rsquo;s safety guarantees have limits</strong>.</p>
<p>In safe Rust, entire classes of memory-safety bugs are eliminated at compile time. You will not find buffer overflows, use-after-free, or data races in safe Rust code. This is a huge win for security.</p>
<p>But Rust does not prevent:</p>
<ul>
<li><strong>Logic bugs</strong>: Trusting user-controlled headers for authentication decisions</li>
<li><strong>Error handling mistakes</strong>: Using <code>.unwrap()</code> on fallible operations with untrusted input</li>
<li><strong>Design flaws</strong>: Exposing sensitive endpoints without proper authentication</li>
<li><strong>Cryptographic errors</strong>: Using weak algorithms or improper key management</li>
</ul>
<blockquote class="admonition admonition-insight">
<strong>Key Insight</strong>
<p>Memory safety is necessary but not sufficient for security. Rust eliminates one category of vulnerabilities, but logic bugs and design flaws require the same careful analysis as in any other language.</p>
</blockquote>
<p>These findings demonstrate why AI-assisted code analysis remains valuable even for memory-safe languages. SecMate identified these vulnerabilities by analyzing data flow and reasoning about how untrusted input affects security decisions, something that applies regardless of the language.</p>
<h2 id="disclosure-timeline">Disclosure Timeline</h2>
<div style="position: relative; padding-left: 1.5rem; margin: 1.5rem 0;">
  <div style="position: absolute; left: 0.35rem; top: 0.5rem; bottom: 0.5rem; width: 2px; background: var(--color-border);"></div>
  <div style="position: relative; padding-bottom: 1.25rem;">
    <div style="position: absolute; left: -1.15rem; top: 0.35rem; width: 10px; height: 10px; border-radius: 50%; background: var(--color-accent); border: 2px solid var(--color-bg);"></div>
    <div style="font-size: 0.75rem; color: var(--color-text-secondary); font-weight: 600;">Dec 8, 2025</div>
    <div style="color: var(--color-text);">SecMate reported both vulnerabilities to RustFS maintainers</div>
  </div>
  <div style="position: relative; padding-bottom: 1.25rem;">
    <div style="position: absolute; left: -1.15rem; top: 0.35rem; width: 10px; height: 10px; border-radius: 50%; background: var(--color-text-secondary); border: 2px solid var(--color-bg);"></div>
    <div style="font-size: 0.75rem; color: var(--color-text-secondary); font-weight: 600;">Dec 28, 2025</div>
    <div style="color: var(--color-text);">Maintainers acknowledged and confirmed the issues</div>
  </div>
  <div style="position: relative; padding-bottom: 1.25rem;">
    <div style="position: absolute; left: -1.15rem; top: 0.35rem; width: 10px; height: 10px; border-radius: 50%; background: #22c55e; border: 2px solid var(--color-bg);"></div>
    <div style="font-size: 0.75rem; color: var(--color-text-secondary); font-weight: 600;">Dec 30, 2025</div>
    <div style="color: var(--color-text);">Patches merged and released</div>
  </div>
  <div style="position: relative; padding-bottom: 1.25rem;">
    <div style="position: absolute; left: -1.15rem; top: 0.35rem; width: 10px; height: 10px; border-radius: 50%; background: #f59e0b; border: 2px solid var(--color-bg);"></div>
    <div style="font-size: 0.75rem; color: var(--color-text-secondary); font-weight: 600;">Jan 7, 2026</div>
    <div style="color: var(--color-text);">CVE-2025-69255 published (<a href="https://github.com/rustfs/rustfs/security/advisories/GHSA-gw2x-q739-qhcr">GHSA-gw2x-q739-qhcr — RustFS gRPC GetMetrics deserialization panic enables remote DoS</a>)</div>
  </div>
  <div style="position: relative;">
    <div style="position: absolute; left: -1.15rem; top: 0.35rem; width: 10px; height: 10px; border-radius: 50%; background: #f59e0b; border: 2px solid var(--color-bg);"></div>
    <div style="font-size: 0.75rem; color: var(--color-text-secondary); font-weight: 600;">Feb 3, 2026</div>
    <div style="color: var(--color-text);">CVE-2026-21862 published (<a href="https://github.com/rustfs/rustfs/security/advisories/GHSA-fc6g-2gcp-2qrq">GHSA-fc6g-2gcp-2qrq — SourceIp bypass via spoofed X-Forwarded-For/Real-IP headers</a>)</div>
  </div>
</div>
<p>We thank the RustFS maintainers for their responsiveness in addressing these issues. Coordinated disclosure helps keep the ecosystem secure.</p>
<h2 id="want-to-know-more">Want to Know More?</h2>
<p>These two CVEs are the first vulnerabilities we are publicly disclosing in a Rust codebase, showcasing SecMate&rsquo;s expanded language support. As Rust adoption grows in systems programming and embedded development, we expect to find more issues like these: logical flaws that memory safety alone cannot prevent.</p>
<p>Interested in our vulnerability research? Browse our <a href="https://secmate.dev/disclosures?utm_source=blog&amp;utm_medium=body&amp;utm_campaign=rustfs-vulnerabilities-secmate-rust-support&amp;utm_content=security" rel="noopener noreferrer" target="_blank" data-cta-type="body_disclosures" data-post-slug="rustfs-vulnerabilities-secmate-rust-support" data-post-category="security">public disclosures</a> to see what else we have found. If you want SecMate to analyze your codebase, whether it is Rust, C, C++, or another language, <a href="https://secmate.dev/register?utm_source=blog&amp;utm_medium=body&amp;utm_campaign=rustfs-vulnerabilities-secmate-rust-support&amp;utm_content=security" rel="noopener noreferrer" target="_blank" data-cta-type="body_register" data-post-slug="rustfs-vulnerabilities-secmate-rust-support" data-post-category="security">get in touch</a>.</p>
<h2 id="references">References</h2>
<ul>
<li>
<p><a id="ref1"></a>[1] RustFS. &ldquo;RustFS - High Performance Object Storage&rdquo; <em>GitHub</em>. <a href="https://github.com/rustfs/rustfs" rel="noopener noreferrer" target="_blank">Repository</a> | <a href="https://docs.rustfs.com/" rel="noopener noreferrer" target="_blank">Documentation</a></p>
</li>
<li>
<p><a id="ref2"></a>[2] GitHub. &ldquo;GHSA-fc6g-2gcp-2qrq - SourceIp bypass via spoofed X-Forwarded-For/Real-IP headers&rdquo; <em>GitHub Security Advisory</em>. <a href="https://github.com/rustfs/rustfs/security/advisories/GHSA-fc6g-2gcp-2qrq" rel="noopener noreferrer" target="_blank">Advisory</a></p>
</li>
<li>
<p><a id="ref3"></a>[3] GitHub. &ldquo;GHSA-gw2x-q739-qhcr - RustFS gRPC GetMetrics deserialization panic enables remote DoS&rdquo; <em>GitHub Security Advisory</em>. <a href="https://github.com/rustfs/rustfs/security/advisories/GHSA-gw2x-q739-qhcr" rel="noopener noreferrer" target="_blank">Advisory</a></p>
</li>
</ul>
<hr>
<p><em>The SecMate Team</em></p>
]]></content:encoded><media:content url="https://blog.secmate.dev/images/og_image.jpg" medium="image"/></item></channel></rss>