<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Tiemoko Ballo</title>
    <subtitle>{Soft,Firm}ware Security</subtitle>
    <link rel="self" type="application/atom+xml" href="https://tiemoko.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://tiemoko.com"/>
    <updated>2025-07-06T00:00:00+00:00</updated>
    <id>https://tiemoko.com/atom.xml</id>
    <entry xml:lang="en">
        <title>Tactical Trust (1 of 2): Platform Crypto for Developers</title>
        <published>2025-07-06T00:00:00+00:00</published>
        <updated>2025-07-06T00:00:00+00:00</updated>
        <rights type="html">&amp;copy; 2020-2025 Tiemoko Ballo</rights>
        
        <author>
          <name>
            
              Tiemoko Ballo
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tiemoko.com/blog/safer-crypto/"/>
        <id>https://tiemoko.com/blog/safer-crypto/</id>
        
        <content type="html" xml:base="https://tiemoko.com/blog/safer-crypto/">&lt;hr &#x2F;&gt;
&lt;!---
* Title and divide on same line
* Box border for manually-designated lists
---&gt;
&lt;style&gt;
    .title-divider {
        display: flex;
        flex-wrap: nowrap;
        align-items: center;
    }

    .title {
        flex: 1;
        flex-grow: 0.001;
        flex-shrink: 0.001;
        flex-basis: auto;
        white-space: normal;
        text-align: left;
        padding-right: 0.5rem;
    }

    .divider {
        flex: 1;
        flex-grow: 1;
        flex-shrink: 1;
        flex-basis: 0;
        height: 2px;
        background-color: #9a9a9a;
        margin-top: 0.75rem;
    }

    ul.boxed {
      border: 2px solid #9a9a9a;
      margin-top: 1rem;
      padding-bottom: 1rem;
      padding-top: 1rem;
      padding-left: 2rem;
      padding-right: 2rem;
    }
&lt;&#x2F;style&gt;
&lt;!---
* Side-by-side diagrams
---&gt;
&lt;style&gt;
  .diagram-row {
    display: flex;
    justify-content: space-evenly;
    align-items: center;
  }

  .diagram-col {
    flex: 50%;
    max-width: 35%;
    padding-top: 1%;
    padding-bottom: 4%;
  }

  .diagram-col2 {
    flex: 50%;
    max-width: 40%;
    padding-top: 1%;
    padding-bottom: 4%;
  }

   .diagram-solo {
    flex: 100%;
    max-width: 75%;
    padding-top: 1%;
    padding-bottom: 4%;
  }
&lt;&#x2F;style&gt;
&lt;p&gt;Digital systems our society relies on all have some notion of &lt;strong&gt;trust&lt;&#x2F;strong&gt;.
A communicating party can identify, with confidence, &lt;em&gt;who&lt;&#x2F;em&gt; they are &quot;talking&quot; to (authentication).
And they can rest assured that their &quot;conversation&quot; is &lt;em&gt;private&lt;&#x2F;em&gt; (confidentiality).
Even non-networked systems will validate that code they flash or execute hasn&#x27;t been &lt;em&gt;modified&lt;&#x2F;em&gt; or &lt;em&gt;corrupted&lt;&#x2F;em&gt; (integrity).&lt;&#x2F;p&gt;
&lt;p&gt;Cryptographic libraries are the technical mechanism underpinning properties like authentication, confidentiality, and integrity.
These imperfect software components are the foundation on which societal trust is built and maintained.
Thus exploitable flaws in crypto libs tend to have severe and widespread impact - e.g. &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;dl.acm.org&#x2F;doi&#x2F;pdf&#x2F;10.1145&#x2F;2663716.2663755&quot;&gt;[Durumeric, 2014]&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now this two-part post series isn&#x27;t about applied cryptography in the proper academic sense, we won&#x27;t explain cryptographic primitives or protocol design from the ground up.
Let&#x27;s assume those more formal concepts live in an &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Ivory_tower&quot;&gt;ivory tower&lt;&#x2F;a&gt;.
We&#x27;re medieval peasants fighting in mud that is long-surviving production software - shipping, patching, refactoring.&lt;&#x2F;p&gt;
&lt;p&gt;These posts are concerned with brutal realities of deploying [theoretically] sound designs - we aim to reduce certain risks inherent to real-world software.
It&#x27;s one interpretation of what &lt;strong&gt;platform security engineering&lt;&#x2F;strong&gt; entails when shipping trust at scale.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;How are we defining &quot;platform security engineering&quot;?&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Building libraries, frameworks, and tools that allow feature teams to ship both securely and quickly.
Essentially providing a &quot;solid security foundation&quot; for high-velocity software.
In terms of code-level consistency.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;We&#x27;ll use Rust, an increasingly popular systems programming language that &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tiemoko.com&#x2F;blog&#x2F;blue-team-rust&#x2F;&quot;&gt;guarantees memory safety&lt;&#x2F;a&gt; and tends to encourage functional correctness in limited yet substantial ways.
Prior Rust experience isn&#x27;t required, but will help &lt;em&gt;maximize&lt;&#x2F;em&gt; understanding (and enjoyment?).
Concepts we cover are language-agnostic: they likely apply to your problem domain and tech stack of choice.&lt;&#x2F;p&gt;
&lt;div class=&quot;title-divider&quot;&gt;
  &lt;div class=&quot;title&quot;&gt;&lt;h2&gt;So what&#x27;s the agenda for this two-part series?&lt;&#x2F;h2&gt;&lt;&#x2F;div&gt;
  &lt;div class=&quot;divider&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&lt;strong&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tiemoko.com&#x2F;blog&#x2F;safer-crypto&#x2F;&quot;&gt;Part 1&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; (this post) focuses on &lt;em&gt;code&lt;&#x2F;em&gt; (full, runnable &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tnballo&#x2F;high-assurance-rust&#x2F;blob&#x2F;main&#x2F;code_snippets&#x2F;chp14&#x2F;tactical_trust&quot;&gt;source here&lt;&#x2F;a&gt;).
Our proof-of-concept programs aim to raise the bar for &quot;shift left&quot; automation, even if modestly (give the attacker an inch, they&#x27;ll take a mile).
We&#x27;ll sample solutions to two cryptographic platform security problems at different levels of the stack:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;🔐 &lt;span class=&quot;title-sub&quot;&gt;&lt;b&gt;API&lt;span class=&quot;title-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;b&gt;&lt;&#x2F;span&gt; Can we systematically prevent nonce reuse vulnerabilities in an arbitrarily-large codebase?&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;🔗 &lt;span class=&quot;title-sub&quot;&gt;&lt;b&gt;Supply-chain&lt;span class=&quot;title-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;b&gt;&lt;&#x2F;span&gt; How should CI enforce policies specific to cryptographic dependencies?&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tiemoko.com&#x2F;blog&#x2F;%3Cplaceholder%3E&#x2F;&quot;&gt;Part 2&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; will focus on &lt;em&gt;concepts&lt;&#x2F;em&gt; but still include plenty of code. The emphasis is higher-level exploration of a {problem,solution} space.
We&#x27;ll narrow scope to the problem of &lt;em&gt;information disclosure&lt;&#x2F;em&gt;, deep-diving vulnerabilities and state-of-the-art mitigations through the lens of two general threat models:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;📡 &lt;span class=&quot;title-sub&quot;&gt;&lt;b&gt;Man-in-the-Middle (MITM)&lt;span class=&quot;title-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;b&gt;&lt;&#x2F;span&gt; Attacker intercepts network communications between two or more endpoints.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;💻 &lt;span class=&quot;title-sub&quot;&gt;&lt;b&gt;Man-at-the-End (MATE)&lt;span class=&quot;title-separator&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;b&gt;&lt;&#x2F;span&gt; Attacker directly compromises one or more communication endpoints.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;What if I&#x27;m interested less in software engineering, more in cryptographic design?&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;futurama.fandom.com&#x2F;wiki&#x2F;Good_news,_everyone!&quot;&gt;Good news, everyone!&lt;&#x2F;a&gt;
Although we&#x27;re focused on code-level tactics, there&#x27;s several quality, strategy-focused resources to meet you wherever you&#x27;re currently at and help you construct correct designs. Here&#x27;s a sample:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Crypto novice but an experienced developer? → &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;amzn.to&#x2F;43ov045&quot;&gt;&quot;Real-world Cryptography&quot; by Dave Wong&lt;&#x2F;a&gt;
&lt;br&gt;&lt;br&#x2F;&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Work in applied cryptography professionally? → &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;soatok.blog&#x2F;category&#x2F;cryptography&#x2F;&quot;&gt;Soatok&#x27;s Cryptography Blog&lt;&#x2F;a&gt;
&lt;br&gt;&lt;br&#x2F;&gt;&lt;&#x2F;li&gt;
&lt;li&gt;At the cutting-edge of near-future cryptography? → &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rwc.iacr.org&#x2F;&quot;&gt;Real World Crypto Symposium&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;div class=&quot;title-divider&quot;&gt;
  &lt;div class=&quot;title&quot;&gt;&lt;h2&gt;&amp;#x1F510; &lt;span class=&quot;title-sub&quot;&gt;API&lt;&#x2F;span&gt;&lt;span class=&quot;title-separator&quot;&gt;:&lt;&#x2F;span&gt; Prevent Nonce Reuse with Stronger Types&lt;&#x2F;h2&gt;&lt;&#x2F;div&gt;
  &lt;div class=&quot;divider&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&quot;Nonce&quot; is a portmanteau of &quot;&lt;span style=&quot;text-decoration: underline;&quot;&gt;n&lt;&#x2F;span&gt;umber used only &lt;span style=&quot;text-decoration: underline;&quot;&gt;once&lt;&#x2F;span&gt;&quot;.
As the name implies: accidentally using the same nonce multiple times, aka &lt;em&gt;nonce reuse&lt;&#x2F;em&gt;, is a devastating footgun for many widely-used cryptographic algorithms.
Common operations rely on a random nonce as input in order to uphold critical security properties:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Encryption&lt;&#x2F;strong&gt; - Unique nonces are often called &quot;Initialization Vectors&quot; (IVs). They prevent &lt;em&gt;plaintext and&#x2F;or key recovery&lt;&#x2F;em&gt; as well as &lt;em&gt;replay attacks&lt;&#x2F;em&gt; (malicious repetition of previous communications).&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;WPA2 was the de facto standard for encryption on Wi-Fi networks from 2006 to 2020. Toward the end of that lifespan, researchers demonstrated a practical attack against all implementations &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;papers.mathyvanhoef.com&#x2F;ccs2017.pdf&quot;&gt;[Vanhoef, 2017]&lt;&#x2F;a&gt;. By abusing re-transmission logic in the 4-way handshake between a Wi-Fi endpoint and a client joining the network, an attacker could force &lt;em&gt;reset&#x2F;reuse&lt;&#x2F;em&gt; of the nonce&#x2F;IV for all protocol-supported stream ciphers (e.g. &quot;keystream reuse&quot;). That means an attacker can decrypt, replay, and [in some cases] forge network packets. Full compromise of the transport layer (e.g. TCP but not HTTPS).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Signing&lt;&#x2F;strong&gt; - Unique nonces prevent &lt;em&gt;signature forging&lt;&#x2F;em&gt; (generating a passing signature for attacker-created data) and &lt;em&gt;signature duplication&lt;&#x2F;em&gt; (replay of previously-signed data).&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The Sony PlayStation 3 was poised to become the most secure game console ever made, with no true jailbreak 4 years into production. The PS3 used ECDSA to create a chain-of-trust from early boot to userspace app launch - cryptographically enforcing software license checks. ECDSA signing takes as input a nonce and a hash of data to sign. Hackers discovered  that Sony&#x27;s implementation used a hardcoded nonce &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=DUGGJpn2_zY&quot;&gt;[FailOverflow, 2010]&lt;&#x2F;a&gt;. This flaw enabled trivial re-computation of the ECDSA &lt;em&gt;private&lt;&#x2F;em&gt; signing key and therefore attacker ability to execute arbitrary unlicensed software.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;br&gt;
&lt;body&gt;
  &lt;div class=&quot;diagram-row&quot;&gt;
    &lt;div class=&quot;diagram-solo&quot;&gt;
      &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;tt_nonce_reuse.svg&quot; alt=&quot;Nonce reuse in context of encryption&quot;&gt;
      &lt;br&gt;
      &lt;figcaption&gt;&lt;i&gt;&lt;center&gt;&lt;b&gt;Fig. 1:&lt;&#x2F;b&gt; Nonce reuse: a single nonce used for multiple encryption operations (red input, step 3+).&lt;&#x2F;center&gt;&lt;&#x2F;i&gt;&lt;&#x2F;figcaption&gt;
    &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;body&gt;
&lt;p&gt;So then: how do we prove that, in some arbitrarily-large codebase, all nonces are both random and single-use?
By encoding safety invariants into the language&#x27;s &lt;em&gt;type system&lt;&#x2F;em&gt;.
We can create APIs that are nearly impossible to misuse, and we get automatic static verification of that correctness just by compiling a program which uses exclusively the safe APIs!&lt;&#x2F;p&gt;
&lt;p&gt;Bold claim, yet relatively straight-forward implementation:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#ffffff;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;aead::{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    Aead, AeadCore, Nonce, Payload,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    rand_core::{CryptoRng, RngCore},
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;};
&lt;&#x2F;span&gt;&lt;span&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;core::error::Error;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Can be used in arbitrarily many decryption operations.
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Its counterpart, [`EncryptionNonce`], can only be used for one encryption operation.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub type &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;DecryptionNonce&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt; = &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Nonce&amp;lt;A&amp;gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; A safer nonce type for AEAD. See trait [`NonceSafeAead`].
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; SECURITY: Intentionally opaque and unique. Do not derive&#x2F;implement any of:
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; `Default`, `Copy`, `Clone`, `Ord`, `Eq`, `Debug`, etc.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;EncryptionNonce&amp;lt;A: AeadCore&amp;gt;(Nonce&amp;lt;A&amp;gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;A: AeadCore&amp;gt; EncryptionNonce&amp;lt;A&amp;gt; {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Generate a new random nonce for AEAD-specific encryption.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span&gt;generate_nonce&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;rng&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: impl CryptoRng + RngCore) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        EncryptionNonce(&lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;A &lt;&#x2F;span&gt;&lt;span&gt;as&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; AeadCore&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::generate_nonce(rng))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Crate-private conversion into [`aead::Nonce`].
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; SECURITY: Do not make `pub`, risks reuse with `aead::Aead` APIs.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span&gt;less_safe_to_raw_nonce&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; Nonce&amp;lt;A&amp;gt; {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;0
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Nonce-safe AEAD. Guarantees the following properties:
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; 1. Nonce is random.
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F;     * Opaque type with rand-only constructor.
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; 2. Nonce is used in exactly one encryption operation.
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F;     * Pass-by-value consumption.
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; See also: [`EncryptionNonce`] and [`DecryptionNonce`].
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub trait &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;NonceSafeAead {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Encrypt plaintext payload with a random, single-use nonce.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Returns ciphertext bytes and decryption-only nonce.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span&gt;nonce_safe_encrypt&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;msg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;aad&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;(
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;enc_nonce&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: EncryptionNonce&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;plaintext&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Into&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Payload&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;msg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;aad&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    ) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;, DecryptionNonce&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;), impl Error&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span&gt;where
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: AeadCore + Aead + Sized,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; nonce &lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; enc_nonce.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;less_safe_to_raw_nonce&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;encrypt&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;nonce, plaintext)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;ciphertext&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| (ciphertext, nonce))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Decrypt ciphertext.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Identical to [`aead::Aead::decrypt`], defined so that [`aead::Aead`]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; doesn&amp;#39;t have to be brought in-scope when using [`NonceSafeAead`].
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; SECURITY: ban import of less safe `aead::Aead` trait.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span&gt;decrypt&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;msg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;aad&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;(
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;dec_nonce&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;DecryptionNonce&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;ciphertext&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Into&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Payload&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;msg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;&amp;#39;aad&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    ) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;, impl Error&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span&gt;where
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: AeadCore + Aead + Sized,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span&gt;as&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; Aead&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::decrypt(self, dec_nonce, ciphertext)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Use above default impl for below algorithms
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;NonceSafeAead &lt;&#x2F;span&gt;&lt;span&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;chacha20poly1305::XChaCha20Poly1305 {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;NonceSafeAead &lt;&#x2F;span&gt;&lt;span&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;aes_gcm::Aes256Gcm {}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;NonceSafeAead &lt;&#x2F;span&gt;&lt;span&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;aes_siv::Aes256SivAead {}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;aead&#x2F;0.5.2&#x2F;aead&#x2F;trait.Aead.html&quot;&gt;&lt;code&gt;Aead&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is a widely-used trait in the Rust cryptography ecosystem.
It defines a common interface to the &lt;code&gt;encrypt&lt;&#x2F;code&gt; and &lt;code&gt;decrypt&lt;&#x2F;code&gt; operations of Authenticated Encryption with Associated Data (AEAD) algorithms like AES-256-GCM and XChaCha20Poly1305.
This class of algorithms provides both confidentiality and integrity, plus optionally allows binding unencrypted, &quot;associated&quot; metadata (think network headers, UUIDs, or contextual info).
Basically, an AEAD should be your preferred all-in-one solution for most day-to-day encryption problems.&lt;&#x2F;p&gt;
&lt;p&gt;Now the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;aead&#x2F;0.5.2&#x2F;aead&#x2F;trait.Aead.html#tymethod.encrypt&quot;&gt;&lt;code&gt;Aead&lt;&#x2F;code&gt; enc&#x2F;decrypt APIs&lt;&#x2F;a&gt; both take a single nonce type by reference: &lt;code&gt;&amp;amp;Nonce&amp;lt;A: AeadCore&amp;gt;&lt;&#x2F;code&gt;. So a programmer is free to encrypt new data with the same nonce they used for decryption earlier (see Figure 1 above).&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Notice how a nonce is generic over the &lt;code&gt;AeadCore&lt;&#x2F;code&gt; trait, allowing &lt;em&gt;compile-time&lt;&#x2F;em&gt; verification of algorithm-specific array sizes - e.g. &lt;code&gt;[u8; 12]&lt;&#x2F;code&gt; (96-bit) for AES-256-GCM, &lt;code&gt;[u8; 24]&lt;&#x2F;code&gt; (192-bit) for XChaCha20Poly1305 - at &lt;em&gt;all&lt;&#x2F;em&gt; call-sites.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The crux of our above reuse solution is this: we use two distinct nonce types, &lt;code&gt;EncryptionNonce&amp;lt;A: AeadCore&amp;gt;&lt;&#x2F;code&gt; for &lt;code&gt;encrypt&lt;&#x2F;code&gt; and &lt;code&gt;DecryptionNonce&amp;lt;A: AeadCore&amp;gt;&lt;&#x2F;code&gt; for &lt;code&gt;decrypt&lt;&#x2F;code&gt;.
This bifurcation prevents nonce-reuse vulnerabilities, again at &lt;em&gt;compile-time&lt;&#x2F;em&gt; (before shipping and systematically across the entire codebase), because:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;EncryptionNonce&lt;&#x2F;code&gt; is guaranteed to be &lt;em&gt;randomly-generated&lt;&#x2F;em&gt; (opaque type with rand-only constructor) and &lt;em&gt;single-use&lt;&#x2F;em&gt; (pass-by-value parameter semantics). The single-use property is especially amenable to Rust&#x27;s [linear] type system. Its decryption counterpart, alias &lt;code&gt;type DecryptionNonce&amp;lt;A&amp;gt; = Nonce&amp;lt;A&amp;gt;;&lt;&#x2F;code&gt;, continues to work normally.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rand_core&#x2F;0.9.3&#x2F;rand_core&#x2F;trait.CryptoRng.html&quot;&gt;Marker trait &lt;code&gt;CryptoRng&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; in &lt;code&gt;fn generate_nonce(rng: impl CryptoRng + RngCore)&lt;&#x2F;code&gt; is critical. A &lt;em&gt;biased&lt;&#x2F;em&gt; (meaning not uniformly random) nonce can be as disastrous as a reused nonce. In another ECDSA debacle, biased nonces allowed extraction of Bitcoin private keys &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;eprint.iacr.org&#x2F;2019&#x2F;023.pdf&quot;&gt;[Breitner, 2019]&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;What about &quot;nonce misuse-resistant&quot; algorithms? And size limitations?&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Strong typing isn&#x27;t the only possible solution for nonce-reuse.
Defenses can also be implemented in the design of the algorithm itself, see &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;rfc8452&quot;&gt;AES-GCM-SIV&lt;&#x2F;a&gt;.
A &quot;Synthetic Initialization Vector&quot; (SIV) uses inputs, including plaintext, to derive the final IV&#x2F;nonce - effectively forcing two different plaintexts to use two different nonces.&lt;&#x2F;p&gt;
&lt;p&gt;However: if the &lt;em&gt;same message&lt;&#x2F;em&gt; is encrypted with the &lt;em&gt;same nonce&lt;&#x2F;em&gt; &lt;span style=&quot;text-decoration: underline;&quot;&gt;twice&lt;&#x2F;span&gt; under the &lt;em&gt;same key&lt;&#x2F;em&gt;, an attacker will learn that the two messages are equivalent (but not their contents).
That equivalence leak could have serious implications in context of a larger threat model, so preventing reuse with strong typing is still the higher assurance option.&lt;&#x2F;p&gt;
&lt;p&gt;But we&#x27;re not out of the woods yet.
AES-256-GCM can only safely encrypt &lt;a href=&quot;https:&#x2F;&#x2F;www.imperialviolet.org&#x2F;2015&#x2F;05&#x2F;16&#x2F;aeads.html&quot;&gt;2&lt;sup&gt;32&lt;&#x2F;sup&gt; (~4.3 billion) messages&lt;&#x2F;a&gt; under the same key using random nonces - beyond that we risk &lt;em&gt;nonce collision&lt;&#x2F;em&gt; (chance reuse). XChaCha20Poly1305 bumps that safe limit to &lt;a href=&quot;https:&#x2F;&#x2F;datatracker.ietf.org&#x2F;doc&#x2F;html&#x2F;draft-irtf-cfrg-xchacha-03#section-2.1&quot;&gt;2&lt;sup&gt;80&lt;&#x2F;sup&gt; (practically infinite!)&lt;&#x2F;a&gt; and is faster on devices without hardware support for AES.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;We can verify that the &lt;code&gt;NonceSafeAead&lt;&#x2F;code&gt; trait enc&#x2F;decrypts as expected with the below unit test:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#ffffff;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;aead::{KeyInit, OsRng};
&lt;&#x2F;span&gt;&lt;span&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;nonce_typing::{EncryptionNonce, NonceSafeAead};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PLAINTEXT_MSG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;86&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;] &lt;&#x2F;span&gt;&lt;span&gt;=
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;Two cryptographers walk into a bar. Nobody else has a clue what they&amp;#39;re talking about.&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;#[test]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span&gt;nonce_safe_xchacha20poly1305&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;chacha20poly1305::XChaCha20Poly1305;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; key &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;XChaCha20Poly1305::generate_key(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; OsRng);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; cipher &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;XChaCha20Poly1305::new(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;key);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; enc_nonce &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;EncryptionNonce::&amp;lt;XChaCha20Poly1305&amp;gt;::generate_nonce(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; OsRng);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(ciphertext, dec_nonce) &lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; cipher
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;nonce_safe_encrypt&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(enc_nonce, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PLAINTEXT_MSG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;())
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; plaintext &lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; cipher.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;decrypt&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;dec_nonce, ciphertext.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    assert_eq!(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;plaintext, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;PLAINTEXT_MSG&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But does it actually prevent reuse?
You&#x27;re welcome to try passing the same &lt;code&gt;enc_nonce&lt;&#x2F;code&gt; to two different &lt;code&gt;nonce_safe_encrypt&lt;&#x2F;code&gt; calls - the compiler error should look familiar!&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Where do I start with &quot;formally verified&quot; cryptography?&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Proving that a program satisfies a specific property, for any input, is the goal of &lt;em&gt;formal verification&lt;&#x2F;em&gt;.
Rust&#x27;s type system, which guarantees that data is &quot;shared XOR mutable&quot;, is particularly amenable to certain formal techniques - less reasoning about the state of memory is needed.
Cryptography is also lower-cost to verify: detailed specifications exist, data structures are statically-allocated, and input size is bounded.&lt;&#x2F;p&gt;
&lt;p&gt;Verification techniques vary widely (theorem proving, model checking, abstract interpretation, symbolic execution, etc) and the corresponding tools typically require significant expertise to leverage.
But as &lt;del&gt;lazy&lt;&#x2F;del&gt; busy developers, we can readily integrate and benefit from already-formally-verified libraries.
Two contenders for native cryptography are:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;aws-lc-rs&quot;&gt;&lt;code&gt;aws-lc-rs&lt;&#x2F;code&gt; (Amazon)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; - Symbolic execution of source code is used to prove that a program matches a machine-readable specification manually encoded from an algorithm&#x27;s human-readable specification.
&lt;br&gt;&lt;br&#x2F;&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;symcrypt&quot;&gt;&lt;code&gt;symcrypt&lt;&#x2F;code&gt; (Microsoft)&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt; - Source is translated to a model for an interactive (meaning semi-manual) theorem prover. Additionally, a combination of fuzzing and model-based testing is used to detect timing side-channels.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Keep in mind that formal verification is not a panacea: specifications can be incomplete and implementations can deviate from models.
The aforementioned WPA2 4-way handshake was formally verified yet still exploitable!
Its proof failed to specify when a negotiated key should be installed, implicitly allowing multiple installations and thus nonce reset on next install &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;papers.mathyvanhoef.com&#x2F;ccs2017.pdf&quot;&gt;[Vanhoef, 2017]&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;div class=&quot;title-divider&quot;&gt;
  &lt;div class=&quot;title&quot;&gt;&lt;h2&gt;&amp;#x1f517; &lt;span class=&quot;title-sub&quot;&gt;Supply-chain&lt;&#x2F;span&gt;&lt;span class=&quot;title-separator&quot;&gt;:&lt;&#x2F;span&gt; Allowlist Crypto Publishers and Ban Duplicates&lt;&#x2F;h2&gt;&lt;&#x2F;div&gt;
  &lt;div class=&quot;divider&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Programming languages with official package registries are a joy to use: easily finding and integrating 3rd-party libraries means faster delivery speed and greater focus on your problem&#x2F;business domain.
But all convenience has a cost.
Here:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Increased attack surface&lt;&#x2F;strong&gt; - Just one malicious crate, no matter how deep in a massive dependency graph, can compromise the entire &lt;em&gt;application&lt;&#x2F;em&gt;. And typo-squatting attacks indiscriminately victimize a percentage of the entire &lt;em&gt;ecosystem&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Statistical weakening of memory-safety&lt;&#x2F;strong&gt; - Dependency count likely has some correlation to amount of &lt;code&gt;unsafe&lt;&#x2F;code&gt; Rust code (&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rustfoundation.org&#x2F;media&#x2F;unsafe-rust-in-the-wild-notes-on-the-current-state-of-unsafe-rust&#x2F;&quot;&gt;19% of public crates use &lt;code&gt;unsafe&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;) and other-language CFFI code, and thus amount of total &lt;em&gt;unsound&lt;&#x2F;em&gt; code (realistically some subset of &lt;code&gt;unsafe&lt;&#x2F;code&gt;). Any unsound code can trigger memory safety errors at runtime, which often go undetected in production.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Software bloat&lt;&#x2F;strong&gt; - Transitive dependencies tend to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;spectrum.ieee.org&#x2F;lean-software-development&quot;&gt;sprawl in number&lt;&#x2F;a&gt;, causing &quot;simple&quot; apps to explode in objective size and complexity. Larger programs generally mean slower app startup and longer download times. Plus both routine (e.g. API upgrade) and emergency (e.g. vulnerable dependency alert) maintenance burden.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Supply-chain assurance is particularly important for cryptographic dependencies, which likely have an out-sized impact on the security properties of an overall system. Application logic higher up the stack tends to rely on crypto libraries, implicitly or explicitly.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine you&#x27;ve been handed a strict mandate: the two requirements below &lt;em&gt;must&lt;&#x2F;em&gt; hold for your &lt;em&gt;entire&lt;&#x2F;em&gt; million-plus line monorepo.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Trusted Publishers&lt;&#x2F;strong&gt; - All direct (e.g. non-transitive) cryptographic dependencies must be sourced from a small allowlist of trusted publishers, initially only the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustcrypto&quot;&gt;&lt;code&gt;RustCrypto&lt;&#x2F;code&gt; organization&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Rationale:&lt;&#x2F;strong&gt; Minimize both &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rustsec.org&#x2F;advisories&#x2F;&quot;&gt;RUSTSEC&lt;&#x2F;a&gt; alert volume and backdoor introduction risk.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Scope:&lt;&#x2F;strong&gt; Direct dependencies only. Publishers we explicitly trust can still select their own dependencies.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No Duplicates&lt;&#x2F;strong&gt; - All direct and indirect cryptographic dependencies must have exactly one version in-tree at any time.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Rationale:&lt;&#x2F;strong&gt; Minimize both bloat and programmer error (e.g. unclear behavior divergence between API versions).&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Scope:&lt;&#x2F;strong&gt; All dependencies. Duplicate bloat is likely avoidable - some crate owner should consider updating to latest.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;br&gt;
&lt;body&gt;
  &lt;div class=&quot;diagram-row&quot;&gt;
    &lt;div class=&quot;diagram-col2&quot;&gt;
      &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;tt_supplychain_1.svg&quot; alt=&quot;Before supply-chain policy enforcement&quot;&gt;
      &lt;br&gt;
      &lt;figcaption&gt;&lt;i&gt;&lt;center&gt;&lt;b&gt;Fig. 2:&lt;&#x2F;b&gt; No supply-chain policy. Tolerate organic dependency sprawl.&lt;&#x2F;center&gt;&lt;&#x2F;i&gt;&lt;&#x2F;figcaption&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;diagram-col&quot;&gt;
      &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;tt_supplychain_2.svg&quot; alt=&quot;After supply-chain policy enforcement&quot;&gt;
      &lt;br&gt;
      &lt;figcaption&gt;&lt;i&gt;&lt;center&gt;&lt;b&gt;Fig. 3:&lt;&#x2F;b&gt; Policy enforced: only trusted publisher, no duplicates. Leaner app overall.&lt;&#x2F;center&gt;&lt;&#x2F;i&gt;&lt;&#x2F;figcaption&gt;
    &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;body&gt;
&lt;p&gt;How do you enforce this policy (which nicely compliments our previous &lt;code&gt;NonceSafeAead&lt;&#x2F;code&gt; APIs)?
Unfortunately these specific requirements can&#x27;t be encoded with &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;EmbarkStudios&#x2F;cargo-deny&quot;&gt;&lt;code&gt;cargo deny&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, a popular and mature dependency graph linter, at the time of this writing (v0.18).
We need to roll some custom kit atop &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cargo_metadata&#x2F;0.20.0&#x2F;cargo_metadata&#x2F;index.html&quot;&gt;&lt;code&gt;cargo_metadata&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s start with &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rust-unofficial.github.io&#x2F;patterns&#x2F;patterns&#x2F;creational&#x2F;builder.html&quot;&gt;builder-pattern&lt;&#x2F;a&gt; boilerplate (our public API):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#ffffff;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;cargo_metadata::{semver::Version, CargoOpt, Metadata, MetadataCommand, Package};
&lt;&#x2F;span&gt;&lt;span&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;std::{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    cell::OnceCell,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    collections::{BTreeMap, BTreeSet, HashMap},
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    fs,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    path::{Path, PathBuf},
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;};
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; A [`Policy`] violation.
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Note: error variants do expose&#x2F;re-export error enums from 3rd-party crates.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;#[allow(missing_docs)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub enum &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;PolicyViolationError {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    DuplicateCrateVersions(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;),
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    DisallowedCategoryPublisher(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;),
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    MetadataReadError(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;),
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; A builder for supply-chain policies.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;#[derive(Default)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub struct &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Policy {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Path to `Cargo.toml` we&amp;#39;re analyzing
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    manifest_path: PathBuf,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Workaround for `OnceCell::get_or_try_init` being nightly-only in Rust 1.88
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    cargo_metadata_result: OnceCell&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Metadata, PolicyViolationError&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; {category}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; `String`s lower-cased at construction time
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    no_dup_cats: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;BTreeSet&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; category: {publisher}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; `String`s lower-cased at construction time
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    cat_pubs: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Option&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;BTreeMap&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, BTreeSet&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;&amp;gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;impl &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Policy {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Create a new policy, construct with path to workspace or crate-specific `Cargo.toml`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;P&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;manifest_path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: P) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Policy, std::io::Error&amp;gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span&gt;where
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        P: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;AsRef&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Path&amp;gt;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; manifest_path &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;fs::canonicalize(manifest_path)&lt;&#x2F;span&gt;&lt;span&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            manifest_path,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            &lt;&#x2F;span&gt;&lt;span&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Default&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::default()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        })
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Rule 1 (Category-specific Trusted Publishers):
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Ensure that a given category only contains crates from a fixed set of trusted publishers.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Assumes input iterator format `(category_1, publisher_1)...(category_n, publisher_n)`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; More then one publisher per category is supported.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span&gt;allowed_category_publishers&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;I, S&amp;gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;cat_pubs&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: I) -&amp;gt; Policy
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span&gt;where
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        I: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Iterator&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;Item = (S, S)&amp;gt;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        S: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Into&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; cat_pubs &lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; cat_pubs.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;peekable&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; cat_pubs.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;peek&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;is_some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; cat_map &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;BTreeMap::new();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;for &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(c, p) &lt;&#x2F;span&gt;&lt;span&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; cat_pubs {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                cat_map
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;entry&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(c.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;to_ascii_lowercase&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;())
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;or_insert&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(BTreeSet::new())
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(p.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;into&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;to_ascii_lowercase&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;());
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            self.cat_pubs &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(cat_map);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        } &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            self.cat_pubs &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;None&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        self
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; ...OMITTED: Rule 2 (Category-specific No Duplicates)...
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Evaluate a built policy against a given workspace&#x2F;crate.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;pub fn &lt;&#x2F;span&gt;&lt;span&gt;run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;(), PolicyViolationError&amp;gt; {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;run_allowed_category_publishers&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;run_no_duplicate_crate_categories&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(())
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To keep the length of this post in check, we&#x27;ll omit implementation of scaffolding for the 2nd policy requirement (no duplicate cryptographic dependencies).
But the logic is mechanically similar to the first requirement and the complete, runnable ≈300 lines of source for both rules is &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tnballo&#x2F;high-assurance-rust&#x2F;blob&#x2F;main&#x2F;code_snippets&#x2F;chp14&#x2F;tactical_trust&#x2F;supplychain_policy&quot;&gt;available here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Notice that the above builder doesn&#x27;t encode anything specific to &lt;em&gt;cryptographic&lt;&#x2F;em&gt; crates - this interface supports arbitrary categories and publishers.
Before we see what usage looks like in practice, lets dig into enforcement logic for whatever trusted publishers the user specified when initializing &lt;code&gt;cat_pubs&lt;&#x2F;code&gt; with a call to &lt;code&gt;allowed_category_publishers&lt;&#x2F;code&gt; (the below are private APIs):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#ffffff;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Collect dependency metadata for the entire workspace with all features enabled.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span&gt;metadata&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Metadata, PolicyViolationError&amp;gt; {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; meta_result &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.cargo_metadata_result.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;get_or_init&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|| {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            MetadataCommand::new()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;manifest_path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.manifest_path)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;features&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(CargoOpt::AllFeatures)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;exec&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| PolicyViolationError::MetadataReadError(e.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()))
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        });
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        meta_result.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;map_err&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| e.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;to_owned&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;())
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Get repo&amp;#39;s publisher by parsing its URL.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; SECURITY: `dep.authors` isn&amp;#39;t reliable - anyone can set any value in their crate&amp;#39;s `Cargo.toml`.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span&gt;get_repo_publisher&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;dep&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;Package) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, PolicyViolationError&amp;gt; {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(repo_url) &lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; dep
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            .repository
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;as_ref&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| url::Url::parse(url).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;())
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(PolicyViolationError::MetadataReadError(format!(
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;Missing or invalid repo URL for crate &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                dep.name
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            )));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        };
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; If `repo_url` == &amp;quot;https:&#x2F;&#x2F;github.com&#x2F;RustCrypto&#x2F;AEADs&#x2F;tree&#x2F;master&#x2F;aes-gcm&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Then `repo_publisher` == &amp;quot;RustCrypto&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(repo_publisher) &lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; repo_url.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;path_segments&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;and_then&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;mut &lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| path.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()) &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(PolicyViolationError::MetadataReadError(format!(
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;Missing publisher name for repo URL &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;{repo_url}&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;#39;&amp;quot;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            )));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        };
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(repo_publisher.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;())
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F;&#x2F; Run category-specific trusted publishers check.
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span&gt;run_allowed_category_publishers&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;) -&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;(), PolicyViolationError&amp;gt; {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;ref&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; cat_pubs) &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.cat_pubs &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;else &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(());
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        };
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; metadata &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; ID direct dependencies
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; direct_deps &lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; metadata
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            .packages
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;pkg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| pkg.manifest_path.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;as_path&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span&gt;== &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.manifest_path)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;pkg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pkg.dependencies)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;flatten&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            .collect::&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;&amp;gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Get full crate info for each ID-ed direct dependency
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; direct_dep_crates &lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; metadata
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            .packages
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;pkg&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| direct_deps.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;any&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;dep&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;| dep.name &lt;&#x2F;span&gt;&lt;span&gt;== *&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;pkg.name));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Find disallowed category-specific publishers, if any
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; dep_crate &lt;&#x2F;span&gt;&lt;span&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; direct_dep_crates {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; cat &lt;&#x2F;span&gt;&lt;span&gt;in &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;dep_crate.categories {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if let &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(expected_pubs) &lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; cat_pubs.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;cat.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;to_ascii_lowercase&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()) {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; actual_publisher &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;Self&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;::get_repo_publisher(dep_crate)&lt;&#x2F;span&gt;&lt;span&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;to_lowercase&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;();
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span&gt;!&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;expected_pubs.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;actual_publisher) {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;return &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Err&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(PolicyViolationError::DisallowedCategoryPublisher(
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                            cat.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(),
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                            actual_publisher,
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                        ));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(())
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;fn metadata&lt;&#x2F;code&gt; does memoized collection of dependency metadata for the entire workspace, with all features enabled. Even if the user specifies 10 requirements for 10 different crate categories, we&#x27;ll run collection exactly once (recall &lt;code&gt;Policy&lt;&#x2F;code&gt; field &lt;code&gt;cargo_metadata_result&lt;&#x2F;code&gt; is a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;beta&#x2F;std&#x2F;cell&#x2F;struct.OnceCell.html&quot;&gt;&lt;code&gt;OnceCell&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;fn get_repo_publisher&lt;&#x2F;code&gt; parses the owner of a repository from its URL. While this logic will extract the publishing &lt;em&gt;user&lt;&#x2F;em&gt; or &lt;em&gt;organization&lt;&#x2F;em&gt; for both GitHub and GitLab URLs, be warned: we&#x27;re not claiming any of the code in this supply-chain half of this post is robust enough for production usage!&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We can&#x27;t rely on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;cargo_metadata&#x2F;0.20.0&#x2F;cargo_metadata&#x2F;struct.Package.html#structfield.authors&quot;&gt;the authors field&lt;&#x2F;a&gt; of &lt;code&gt;cargo_metdata&lt;&#x2F;code&gt;&#x27;s &lt;code&gt;Package&lt;&#x2F;code&gt; struct, which could be maliciously set to impersonate a publisher. We instead use [presumably valid] URLs as a source of truth for publisher identification. PKI will be a superior long-term solution, more on this later.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;fn run_allowed_category_publishers&lt;&#x2F;code&gt; is the bulk of our trusted publishers (requirement 1) logic. We identify direct dependencies of the target project (to which &lt;code&gt;Policy::new&lt;&#x2F;code&gt; takes a &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt; path) and iterate that list to look for any crate which belongs to a user-specified category but isn&#x27;t sourced from a user-allowed publisher for that category.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Crate category labels are optional, but we could extend the builder to support &quot;allowed publisher for any or missing category&quot; - ensuring unexpected publishers don&#x27;t slip in. Our policy evaluation logic also doesn&#x27;t validate user-input category names, a typo will cause checks to pass! Adding validation would be straightforward since &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;categories&quot;&gt;categories are fixed&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So how do we roll out enforcement of our sophisticated policy requirements (category-specific trusted publishers and duplicate elimination)?
The heavy-handed option is leveraging &lt;code&gt;build.rs&lt;&#x2F;code&gt; (&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;reference&#x2F;build-script-examples.html&quot;&gt;Rust build scripts&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#ffffff;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;supplychain_policy::Policy;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;fn &lt;&#x2F;span&gt;&lt;span&gt;main&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    println!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;cargo:rerun-if-changed=build.rs&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    println!(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;cargo:rerun-if-changed=Cargo.toml&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; manifest_dir &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;std::env::var(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;CARGO_MANIFEST_DIR&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;CARGO_MANIFEST_DIR var not set&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; manifest_path &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;std::path::PathBuf::from(manifest_dir).&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;Cargo.toml&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;);
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    Policy::new(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;manifest_path)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;Invalid manifest path&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;allowed_category_publishers&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;([(&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;cryptography&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;rustcrypto&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;)].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;())
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;no_duplicate_crate_categories&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;([&lt;&#x2F;span&gt;&lt;span style=&quot;color:#ffd700;&quot;&gt;&amp;quot;cryptography&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;].&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;())
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;run&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now failing builds for supply-chain policy violations probably isn&#x27;t the best way to make friends with other development teams, even in a smaller organization, unless there&#x27;s a strong regulatory and&#x2F;or business need to do so.
Fortunately the above &lt;code&gt;Policy&lt;&#x2F;code&gt; builder can easily be wrapped in a CLI tool and deployed in &lt;em&gt;blocking&lt;&#x2F;em&gt; or &lt;em&gt;non-blocking&lt;&#x2F;em&gt; CI pipelines, on a workspace-specific basis.
Non-blocking failures can be centrally tracked and automatically triaged.&lt;&#x2F;p&gt;
&lt;p&gt;Our above proof-of-concept didn&#x27;t accommodate exceptions (e.g. &quot;allow this specific named duplicate, still enforce for remainder of category&quot;), but you could quickly extend it to read individual crate&#x2F;publisher names from a [version controlled and &lt;code&gt;CODEOWNERS&lt;&#x2F;code&gt; protected] config file.
Supporting legitimate exceptions, with documented rationale, is realistic - &quot;perfect is the enemy of good&quot;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;What are my other options for supply-chain security in Rust?&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The landscape of Rust&#x27;s supply-chain security tooling is, fortunately, evolving.
Sample projects to be aware of:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Signature-based vulnerability alerting:&lt;&#x2F;strong&gt; &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustsec&#x2F;rustsec&#x2F;blob&#x2F;main&#x2F;cargo-audit&#x2F;README.md&quot;&gt;&lt;code&gt;cargo audit&lt;&#x2F;code&gt;, a free tool&lt;&#x2F;a&gt; to scan your dependency tree for &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rustsec.org&#x2F;advisories&#x2F;&quot;&gt;known-vulnerable&lt;&#x2F;a&gt; crates, is a must-have for production CI. Although a lack of &quot;reachability analysis&quot; (call-graph traversal to determine if your code directly or indirectly calls a vulnerable function) does mean false positives.
&lt;br&gt;&lt;br&#x2F;&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Heuristic-based malware detection:&lt;&#x2F;strong&gt; The Linux Foundation has &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;alpha-omega.dev&#x2F;blog&#x2F;crustabilities-capabilities-rust-and-capslock&#x2F;&quot;&gt;funded development&lt;&#x2F;a&gt; of a Rust counterpart to Go&#x27;s &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;google&#x2F;capslock&quot;&gt;&lt;code&gt;capslock&lt;&#x2F;code&gt; tool&lt;&#x2F;a&gt;. Among other usecases, &lt;code&gt;capslock&lt;&#x2F;code&gt; enumerates &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;google&#x2F;capslock&#x2F;blob&#x2F;main&#x2F;docs&#x2F;capabilities.md#capabilities&quot;&gt;&lt;em&gt;capabilities&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; (file I&#x2F;O, network connectivity, command execution, etc) for a given dependency and alerts if they suddenly change in a new version.
&lt;br&gt;&lt;br&#x2F;&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Trusted publishers:&lt;&#x2F;strong&gt; Future &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rustfoundation.org&#x2F;media&#x2F;improving-supply-chain-security-for-rust-through-artifact-signing&#x2F;&quot;&gt;PKI initiatives&lt;&#x2F;a&gt; may allow cryptographic identification of publishers, a big improvement over our above URL parsing. A &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;3691-trusted-publishing-cratesio.html&quot;&gt;related RFC&lt;&#x2F;a&gt; outlines support for publishing crates from trusted infrastructure, following the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;blog.pypi.org&#x2F;posts&#x2F;2023-04-20-introducing-trusted-publishers&#x2F;&quot;&gt;footsteps of PyPI&lt;&#x2F;a&gt;. Note PKI also means better response capability, although a real-world attack may have already succeeded by the time a build machine pulls a Certificate Revocation List (CRL).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;While Rust&#x27;s intentionally minimal &lt;code&gt;std&lt;&#x2F;code&gt; library is boon for embedded development, it does encourage over-reliance on 3rd-party crates for routine tasks.
For contrast: Go&#x27;s standard library offers &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;go.dev&#x2F;doc&#x2F;security&#x2F;fips140&quot;&gt;FIPS 140-3 compliant cryptography&lt;&#x2F;a&gt; with the flip of a build flag and &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;go.dev&#x2F;blog&#x2F;chacha8rand&quot;&gt;backported a secure RNG&lt;&#x2F;a&gt; to existing programs with only a Go toolchain bump!&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;div class=&quot;title-divider&quot;&gt;
  &lt;div class=&quot;title&quot;&gt;&lt;h2&gt;&lt;span class=&quot;title-sub&quot;&gt;Takeaway&lt;&#x2F;span&gt;&lt;&#x2F;h2&gt;&lt;&#x2F;div&gt;
  &lt;div class=&quot;divider&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;&quot;Trust is earned in drops and lost in buckets&quot;.
That&#x27;s probably a maxim, but it feels especially true in the context of commercial software - a global competition in which any winner, perhaps outside of a few monopolists, can be dethroned at any time.&lt;&#x2F;p&gt;
&lt;p&gt;Now the technical mechanism for trust is cryptography.
Most useful cryptography is implemented and executing, whether on a tiny microcontroller or a beefy server, in the form of code.
And code is notoriously difficult to get right, especially when you&#x27;re shipping a lot of it.&lt;&#x2F;p&gt;
&lt;p&gt;Software quality is as challenging to replicate reliably as it is to measure actionably, if not more so.
Our best hope is automating repeatability.
When the quality criteria is security, automation is one goal of a platform security engineering function.
Which needs to keep pace with the broader engineering organization at minimum, and ideally should accelerate all feature teams.&lt;&#x2F;p&gt;
&lt;p&gt;This first post explored bite-sized solutions to platform cryptography problems at the API (nonce reuse) and supply-chain (dependency policy) levels.
The intent is automating guardrails for &lt;em&gt;human&lt;&#x2F;em&gt; error, but nowadays &lt;em&gt;LLM&lt;&#x2F;em&gt; auto-complete increases vulnerability rate - per both &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;2211.03622&quot;&gt;[Perry, 2023]&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;dl.acm.org&#x2F;doi&#x2F;pdf&#x2F;10.1145&#x2F;3610721&quot;&gt;[Pearce, 2025]&lt;&#x2F;a&gt;.
The good news is that the above techniques should mitigate risks from both sources.
Compile-time checks don&#x27;t care how the code was generated.&lt;&#x2F;p&gt;
&lt;p&gt;Our second and final post will have a narrower but deeper scope.
We&#x27;ll explore a classic topic in trust: &lt;em&gt;information disclosure&lt;&#x2F;em&gt; vulnerabilities.
Part 2 (release date TBD) grapples with technical concepts at greater length and on the cutting edge.
You&#x27;re going to want a coffee for this one.&lt;&#x2F;p&gt;
&lt;p&gt;But it&#x27;ll still be good fun.
Trust me.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Read a free technical book!&lt;&#x2F;strong&gt;
I&#x27;m fulfilling a lifelong dream and writing a book.
It&#x27;s about developing secure and robust systems software.
Although a work-in-progress, the book is freely available online (no paywalls or obligations):
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;highassurance.rs&#x2F;&quot;&gt;https:&#x2F;&#x2F;highassurance.rs&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Usable Insecurity: Bug Preservation via Social Persistence</title>
        <published>2024-01-15T00:00:00+00:00</published>
        <updated>2024-01-15T00:00:00+00:00</updated>
        <rights type="html">&amp;copy; 2020-2025 Tiemoko Ballo</rights>
        
        <author>
          <name>
            
              Tiemoko Ballo
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tiemoko.com/blog/usable-insecurity/"/>
        <id>https://tiemoko.com/blog/usable-insecurity/</id>
        
        <content type="html" xml:base="https://tiemoko.com/blog/usable-insecurity/">&lt;hr &#x2F;&gt;
&lt;p align=&quot;center&quot;&gt;
  &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;ac6_invalid_build.jpg&quot; alt=&quot;AC6 Edit Lock Bypass Build&quot; style=&quot;width:100%&quot;&gt;
  &lt;figcaption&gt;&lt;i&gt;&lt;center&gt;An &lt;b&gt;invalid&lt;&#x2F;b&gt; AC6 character build created after edit lock bypass of the official &quot;G6 Red&quot; build (PS5 share code: J7ADPMGH313X).&lt;&#x2F;center&gt;&lt;&#x2F;i&gt;&lt;&#x2F;figcaption&gt;
&lt;br&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;If everyone could make effective use of security practices and services, we&#x27;d all be better off.
In terms of society&#x27;s collective defensive posture.
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;system&#x2F;files&#x2F;soups2023-mccall.pdf&quot;&gt;&quot;Usable Security&quot;&lt;&#x2F;a&gt; examines human factors solutions toward that goal.&lt;&#x2F;p&gt;
&lt;p&gt;But what about the inverse: how might &lt;strong&gt;human factors&lt;&#x2F;strong&gt; enable &lt;strong&gt;system misuse&lt;&#x2F;strong&gt;?&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll examine a light-hearted, real-world example of &quot;usable insecurity&quot;: generating an &lt;em&gt;invalid&lt;&#x2F;em&gt; game state in &quot;Armored Core 6&quot;, then making &lt;em&gt;remediation&lt;&#x2F;em&gt; more costly and complicated for the developer.
Any player can escalate persistence for this harmless (no piracy&#x2F;cheating&#x2F;data-theft) bug using only the game&#x27;s GUI.
And the deployed defense has palatable tradeoffs.&lt;&#x2F;p&gt;
&lt;p&gt;While this post explores product security topics, it is &lt;em&gt;not&lt;&#x2F;em&gt; a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.exploit-db.com&#x2F;exploits&#x2F;45045&quot;&gt;deeply-technical exploit writeup&lt;&#x2F;a&gt;.
No reverse engineering, asset tampering, runtime instrumentation, social harm, or other potential EULA violations.
We&#x27;re interested in how &quot;power users&quot; can leverage a combo of customization bug and social sharing feature.
Without technical skill or any knowledge of software internals.&lt;&#x2F;p&gt;
&lt;p&gt;With that air-tight disclaimer out of the way: let&#x27;s control cosmetic state in a 3rd-person mech action game.
Words I never anticipated typing on this blog - and you probably didn&#x27;t anticipate reading today.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;What&#x27;s the broader context here, for people that don&#x27;t play video games?&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Armored Core 6: Fires of Rubicon (AC6)&lt;&#x2F;em&gt; is a AAA game by FromSoftware, a critically-acclaimed studio.
It marks both the revival and first commercial mega-success of a Japanese mecha action-simulation game series - which debuted in 1997.
AC6 won the coveted title of &quot;Best Action Game&quot; at the 2023 Game Awards (think Oscars, but gaming).&lt;&#x2F;p&gt;
&lt;p&gt;At the time of this writing AC6 has sold over 2.8 million copies.
The fun bug we&#x27;re dissecting below affects a multi-million person userbase!
A surprising scale in context of an industry-leading product.
With potential lessons, for bugs in more consequential systems.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;understanding-the-user-experience&quot;&gt;Understanding the User Experience&lt;&#x2F;h2&gt;
&lt;p&gt;AC6&#x27;s core &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.makeuseof.com&#x2F;gameplay-loop-gaming&#x2F;&quot;&gt;gameplay loop&lt;&#x2F;a&gt; is centered around micro-optimizing character &quot;builds&quot;.
Builds are combinations of individual combat robot parts, like legs or guns, that give the player an upper-hand in single-player missions and ranked multi-player matches.
Build customization injects a stat-heavy strategy layer into what is otherwise a 3rd-person action game.&lt;&#x2F;p&gt;
&lt;p&gt;AC6 includes an absurdly deep cosmetic customization system for builds - a logo editor&#x2F;creator is bundled-in.
So a &quot;build&quot; is a &lt;em&gt;player configuration&lt;&#x2F;em&gt; with 2 highly-tunable components:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Robot parts (e.g. functional configuration)&lt;&#x2F;li&gt;
&lt;li&gt;Colors&#x2F;logos (e.g. cosmetic configuration)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Players modify settings for these components using nested menus and, for parts, statistics dashboards.&lt;&#x2F;p&gt;
&lt;p&gt;Unlike part tuning, color&#x2F;logo customization is purely aesthetic - it grants no competitive advantage in gameplay.
It&#x27;s also free of micro-transaction monetization (&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.businessofapps.com&#x2F;data&#x2F;fortnite-statistics&#x2F;&quot;&gt;old-school&lt;&#x2F;a&gt;, pro-consumer design).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;attack-bypassing-the-edit-lock-to-generate-invalid-configs&quot;&gt;&lt;span class=&quot;title-sub&quot;&gt;Attack&lt;&#x2F;span&gt;&lt;span class=&quot;title-separator&quot;&gt;:&lt;&#x2F;span&gt; Bypassing the Edit Lock to Generate Invalid Configs&lt;&#x2F;h2&gt;
&lt;p&gt;AC6 players can choose part + color combos freely, with one major exception: official, developer-created character builds are &quot;edit locked&quot;.
Modifying any &lt;strong&gt;part&lt;&#x2F;strong&gt; in an official build requires &lt;em&gt;removing&lt;&#x2F;em&gt; the lock - &lt;em&gt;resetting&lt;&#x2F;em&gt; all special &lt;strong&gt;colors&lt;&#x2F;strong&gt; to default.
The developers&#x27; security goal is:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bind config options:&lt;&#x2F;strong&gt; Make official color-schemes &lt;em&gt;exclusive&lt;&#x2F;em&gt; to official builds. This is a &quot;good state&quot; for builds.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The attacker&#x27;s exploit goal and motivation are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Maximum config control:&lt;&#x2F;strong&gt; Remove official build restrictions. For both greater freedom and otherwise impossible builds. We can think of illegally-generated builds as &quot;bad states&quot;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So every build&#x2F;configuration (some object serialized to local disk for persistence between player logins) has two good&#x2F;valid states:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Locked&lt;&#x2F;strong&gt; - Official colors + official part set.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Unlocked&lt;&#x2F;strong&gt; - Custom colors + official part set &lt;em&gt;or&lt;&#x2F;em&gt; custom parts.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;How are good states maintained when a [potentially nefarious] player drives all settings menus?
With &quot;locking&quot; logic - a series of internal checks and UI warning banners - the game&#x27;s menu system attempts to ensure a build never reaches a bad state:&lt;&#x2F;p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;Invalid&lt;&#x2F;strong&gt; - Official colors + custom parts.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;We can visualize the locked and invalid states.
The dotted-line box represents the edit lock&#x27;s binding, solid gray lines represent color-to-part mappings, and the solid red line (right-hand diagram) is an invalid mapping (lock broken, thus binding broken):&lt;&#x2F;p&gt;
&lt;style&gt;
  .ac6row {
    display: flex;
    justify-content: space-evenly;
    align-items: center;
  }

  .ac6col {
    flex: 50%;
    max-width: 35%;
    padding-top: 1%;
    padding-bottom: 4%;
  }

  .ac6col2 {
    flex: 50%;
    max-width: 40%;
    padding-top: 1%;
    padding-bottom: 4%;
  }
&lt;&#x2F;style&gt;
&lt;body&gt;
  &lt;div class=&quot;ac6row&quot;&gt;
    &lt;div class=&quot;ac6col&quot;&gt;
      &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;ac6_valid.svg&quot; alt=&quot;AC6 good states&quot;&gt;
      &lt;br&gt;
      &lt;figcaption&gt;&lt;i&gt;&lt;center&gt;&lt;b&gt;Fig. 1:&lt;&#x2F;b&gt; Good mappings, lock-enforced.&lt;&#x2F;center&gt;&lt;&#x2F;i&gt;&lt;&#x2F;figcaption&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;ac6col&quot;&gt;
      &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;ac6_invalid.svg&quot; alt=&quot;AC6 good states&quot;&gt;
      &lt;br&gt;
      &lt;figcaption&gt;&lt;i&gt;&lt;center&gt;&lt;b&gt;Fig. 2:&lt;&#x2F;b&gt; New bad mapping, lock bypass.&lt;&#x2F;center&gt;&lt;&#x2F;i&gt;&lt;&#x2F;figcaption&gt;
    &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;body&gt;
&lt;p&gt;So to create an invalid build, the player needs to bypass the edit lock.
Turns out this is trivial!
The AC6 community, including &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;armoredcore&#x2F;comments&#x2F;16czv82&#x2F;simple_trick_to_remove_an_acs_edit_lock&#x2F;&quot;&gt;Reddit users&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=NcNz-H3Hyqo&quot;&gt;YouTube channels&lt;&#x2F;a&gt;, found a simple GUI-only bypass just 2 weeks after the game&#x27;s August 2023 launch.
Steps:&lt;&#x2F;p&gt;
&lt;!---
Internal note for image crops:
- Pos: 1160, 720
- Size: 1520, 720
---&gt;
&lt;style&gt;
  .ac6step {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }

  .ac6img {
    max-width: 40%;
    max-height: 40%;
  }

  .ac6text {
    padding-left: 2%;
    padding-right: 3%;
  }
&lt;&#x2F;style&gt;
&lt;body&gt;
  &lt;br&gt;
  &lt;div class=&quot;ac6step&quot;&gt;
    &lt;div class=&quot;ac6text&quot;&gt;
    &lt;br&gt;1. &lt;b&gt;Load an edit-locked official build: &lt;&#x2F;b&gt; &lt;i&gt;AC DESIGN&lt;&#x2F;i&gt; &gt; &lt;i&gt;AC DATA&lt;&#x2F;i&gt; &gt; &lt;i&gt;PRESET&lt;&#x2F;i&gt; &gt; (select official build) &gt; &lt;i&gt;LOAD&lt;&#x2F;i&gt; &gt; &lt;i&gt;YES&lt;&#x2F;i&gt;.&lt;br&gt;&lt;br&gt;&lt;i&gt;State: &lt;b&gt;locked&lt;&#x2F;b&gt; - parts cannot be edited without losing custom color scheme.&lt;&#x2F;i&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;ac6img&quot;&gt;
      &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;ac6_step_1.jpg&quot;&gt;
    &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
  &lt;div class=&quot;ac6step&quot;&gt;
    &lt;div class=&quot;ac6text&quot;&gt;
    &lt;br&gt;2. &lt;b&gt;Remove the lock from the &lt;i&gt;PAINT&lt;&#x2F;i&gt; menu: &lt;&#x2F;b&gt; &lt;i&gt;AC DESIGN&lt;&#x2F;i&gt; &gt; &lt;i&gt;PAINT&lt;&#x2F;i&gt; &gt; (note &quot;An edit lock is in place for this data...&quot; warning) &gt; &lt;i&gt;YES&lt;&#x2F;i&gt; (remove lock, notice reset color scheme).&lt;br&gt;&lt;br&gt;&lt;i&gt;State: [intermediate&#x2F;transitioning].&lt;&#x2F;i&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;ac6img&quot;&gt;
      &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;ac6_step_2.jpg&quot;&gt;
    &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
  &lt;div class=&quot;ac6step&quot;&gt;
    &lt;div class=&quot;ac6text&quot;&gt;
    &lt;br&gt;3. &lt;b&gt;Exit the &lt;i&gt;PAINT&lt;&#x2F;i&gt; menu without saving changes: &lt;&#x2F;b&gt; (press platform-specific back button) &gt; &lt;i&gt;Discard Edits and Quit.&lt;&#x2F;i&gt;&lt;br&gt;&lt;br&gt;&lt;i&gt;State: &lt;b&gt;invalid&lt;&#x2F;b&gt; (lock bypassed) - keeps official color scheme, sans logo decals, but parts are now fully editable.&lt;&#x2F;i&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;ac6img&quot;&gt;
      &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;ac6_step_3.jpg&quot;&gt;
    &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
  &lt;br&gt;
&lt;&#x2F;body&gt;
&lt;p&gt;That&#x27;s all it takes.
Driving the menus to an unlocked edit state (&lt;em&gt;YES&lt;&#x2F;em&gt; remove lock) and undoing the corresponding color reset (&lt;em&gt;PAINT&lt;&#x2F;em&gt; &amp;gt; &lt;em&gt;Discard Edits and Quit&lt;&#x2F;em&gt;).
Binding broken.&lt;&#x2F;p&gt;
&lt;p&gt;Note invalid builds enable otherwise impossible creations. For example, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;NcNz-H3Hyqo?t=18&quot;&gt;high headlight brightness values&lt;&#x2F;a&gt; can be inherited from the bypassed official build - these values would be fixed and much lower otherwise.&lt;&#x2F;p&gt;
&lt;p&gt;Now that we understand the bug, let&#x27;s look at a way to persist its results.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;battle-patch-delivery-vs-social-replication&quot;&gt;&lt;span class=&quot;title-sub&quot;&gt;Battle&lt;&#x2F;span&gt;&lt;span class=&quot;title-separator&quot;&gt;:&lt;&#x2F;span&gt; Patch Delivery vs. Social Replication&lt;&#x2F;h2&gt;
&lt;p&gt;For a user, builds are labor-intensive outputs.
The player could&#x27;ve spent hours tweaking parameters for a single build file.
So the data is always saved locally.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the kicker: we can replicate build data across other player&#x27;s geographically-distributed systems.
Fully &lt;strong&gt;opt-in&lt;&#x2F;strong&gt; for all parties.
AC6 has &quot;share codes&quot;:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Player A uploads their build and gets a pseudo-random identifier (the &quot;code&quot;).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Player A transmits the code using some out-of-band channel (e.g. private DM, public forum post, etc).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Player B redeems the code (non-exclusive) to download a local copy of player A&#x27;s build data.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Built-in social sharing that works exactly like you&#x27;d expect - solid value add.
You might&#x27;ve already guessed where this is going: sharing invalid builds.
Not a terribly novel idea.
Yet there are at least two big-picture scenarios worth &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;csrc.nist.gov&#x2F;glossary&#x2F;term&#x2F;tabletop_exercise&quot;&gt;table-topping&lt;&#x2F;a&gt; out.&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;body&gt;
  &lt;div class=&quot;ac6row&quot;&gt;
    &lt;div class=&quot;ac6col2&quot;&gt;
      &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;ac6_data_rollback.svg&quot; alt=&quot;Data Rollback (Anti-patch)&quot; style=&quot;width:100%&quot;&gt;
      &lt;br&gt;
      &lt;figcaption&gt;&lt;i&gt;&lt;center&gt;&lt;b&gt;Fig. 3:&lt;&#x2F;b&gt; Sharing an invalid build with a fully-patched client.&lt;&#x2F;center&gt;&lt;&#x2F;i&gt;&lt;&#x2F;figcaption&gt;
    &lt;&#x2F;div&gt;
    &lt;div class=&quot;ac6col2&quot;&gt;
      &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;ac6_dist_persist.svg&quot; alt=&quot;Distributed Persistence (Anti-wipe)&quot; style=&quot;width:100%&quot;&gt;
      &lt;br&gt;
      &lt;figcaption&gt;&lt;i&gt;&lt;center&gt;&lt;b&gt;Fig. 4:&lt;&#x2F;b&gt; Persisting invalid builds across the player base.&lt;&#x2F;center&gt;&lt;&#x2F;i&gt;&lt;&#x2F;figcaption&gt;
    &lt;&#x2F;div&gt;
  &lt;&#x2F;div&gt;
&lt;&#x2F;body&gt;
&lt;p&gt;But first: &lt;strong&gt;opt-in&lt;&#x2F;strong&gt; is worth re-iterating - this design makes invalid builds user-controlled data.
The bug is not &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.vice.com&#x2F;en&#x2F;article&#x2F;the-myspace-worm-that-changed-the-internet-forever&quot;&gt;&quot;worm-able&quot;&lt;&#x2F;a&gt; to unsuspecting clients, copying invalid builds is a player choice.
That&#x27;s best case.
Explicit user authorization is a critical last line of defense, for many &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;learn.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;security&#x2F;application-security&#x2F;application-control&#x2F;user-account-control&#x2F;how-it-works#uac-process-and-interactions&quot;&gt;software systems&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;!--
Think security prompts, privacy toggles, protection disables, etc.
Giving smart humans with a vested interest the choice of optional, lazy-evaluated risk.

[meta] You&#x27;re reading my site&#x27;s source aren&#x27;t you? Hi from one hacker to another :)

Here&#x27;s a flag{e4st3r_e66}:
- Full-size opening invalid build screenshot (J7ADPMGH313X): https:&#x2F;&#x2F;tiemoko.com&#x2F;images&#x2F;ac6_invalid_build_large.jpg
- Full-size PoC screenshot (G1DKZZV8GEUC): https:&#x2F;&#x2F;tiemoko.com&#x2F;images&#x2F;ac6_preorder_export_poc_large.jpg
--&gt;
&lt;p&gt;Now when player B redeems a code the shared build is &lt;em&gt;re-locked&lt;&#x2F;em&gt; on download.
Player B must locally repeat the bypass to gain full edit control.
So social sharing doesn&#x27;t propagate the bypassed state itself, only the resulting invalid build.
The existence of lock-on-download logic implies the edit lock is intended to bind configuration for &lt;em&gt;shared&lt;&#x2F;em&gt; builds - not just &lt;em&gt;official&lt;&#x2F;em&gt; builds.&lt;&#x2F;p&gt;
&lt;p&gt;We omitted this nuance earlier, for simplicity, but the ramification is important: the edit lock has the same failure mode for &lt;em&gt;two&lt;&#x2F;em&gt; distinct usecases, it fails to protect &lt;em&gt;both&lt;&#x2F;em&gt; &lt;strong&gt;developer-generated&lt;&#x2F;strong&gt; and &lt;strong&gt;user-generated&lt;&#x2F;strong&gt; content.&lt;&#x2F;p&gt;
&lt;p&gt;With those caveats out of the way, we&#x27;ll examine our two persistence scenarios.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-data-rollback-anti-patch&quot;&gt;&lt;em&gt;&lt;span class=&quot;title-sub&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;title-separator&quot;&gt;.&lt;&#x2F;span&gt; Data Rollback &lt;span class=&quot;title-separator&quot;&gt;(Anti-patch)&lt;&#x2F;span&gt;&lt;&#x2F;em&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;As of patch version 1.05, the edit lock bypass hasn&#x27;t been fixed.
FromSoftware may well intentionally leave it in, we can&#x27;t be certain.
Maybe it could even be made an official achievement for good sport.&lt;&#x2F;p&gt;
&lt;p&gt;But suppose the developer opts to patch.
The reasonable fix is to stop creation of &lt;em&gt;new&lt;&#x2F;em&gt; invalid&#x2F;bypassed builds without deleting &lt;em&gt;existing&lt;&#x2F;em&gt; save data.
So players don&#x27;t experience sudden remote wipe of their meticulous customization work (e.g. data loss).&lt;&#x2F;p&gt;
&lt;p&gt;Then post-patch users (e.g. those running the latest release) can&#x27;t create an invalid build locally.
But they &lt;em&gt;can&lt;&#x2F;em&gt; download one created previously, via share code.
That means fully-patched clients can &lt;em&gt;roll back&lt;&#x2F;em&gt; their game data to a &quot;bad&quot; state (see figure 3 above), which should have only been reachable in an unpatched client.
And that bad state won&#x27;t be fixed by future patches.&lt;&#x2F;p&gt;
&lt;p&gt;One way to prevent this scenario, without data loss, is selective blocking of share codes: disallow any which IDs an invalid build.
For strong enforcement, blocking needs to be done &lt;em&gt;server-side&lt;&#x2F;em&gt; and on &lt;em&gt;upload&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Let&#x27;s imagine, for the sake of experiment, that FromSoftware chooses the nuclear option - server-side block all relevant social share codes &lt;em&gt;and&lt;&#x2F;em&gt; remote wipe all client-local invalid builds (forced user data loss).
Single goal: no survivors.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-distributed-persistence-anti-wipe&quot;&gt;&lt;em&gt;&lt;span class=&quot;title-sub&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;title-separator&quot;&gt;.&lt;&#x2F;span&gt; Distributed Persistence &lt;span class=&quot;title-separator&quot;&gt;(Anti-wipe)&lt;&#x2F;span&gt;&lt;&#x2F;em&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;When a player transmits a share code, they can do so on a broadcast channel - post it publicly for anyone to download.
Broadcast sharing means attack asymmetry: a single share ID has the potential to replicate build data across &lt;code&gt;N&lt;&#x2F;code&gt; clients (figure 4).&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Proof-of-Concept:&lt;&#x2F;strong&gt; G1DKZZV8GEUC is a PS5 share code for the &quot;G13 Raven&quot; official build (sans decals) - created using the above edit lock bypass. This build was an exclusive pre-order bonus, and can&#x27;t be acquired otherwise. You can re-bypass and save a local copy for offline use :)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In the general case, as &lt;code&gt;N&lt;&#x2F;code&gt; gets higher the probability of a complete (all affected clients) remote delete gets lower.
Maybe there&#x27;s some legal&#x2F;process&#x2F;risk hurdle to data deletion.
Maybe client connectivity is intermittent.
Maybe offline, whole-system backups have already been made (think enterprise environment).
Or maybe users intentionally keep systems offline to retain bad state (a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;5Cq3K9lBli0?feature=shared&amp;amp;t=330&quot;&gt;common practice&lt;&#x2F;a&gt; for game consoles with known-vulnerable firmware, for &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Homebrew_(video_games)&quot;&gt;homebrew&lt;&#x2F;a&gt; XOR piracy reasons).
In every scenario, it&#x27;s challenging to &lt;em&gt;strongly guarantee&lt;&#x2F;em&gt; deletion of &lt;code&gt;N&lt;&#x2F;code&gt; copies across &lt;code&gt;N&lt;&#x2F;code&gt; nodes as &lt;code&gt;N&lt;&#x2F;code&gt; gets huge (maybe multi-million).&lt;&#x2F;p&gt;
&lt;p&gt;Now AC6 is a high-margin product, both in unit sales (e.g. physical&#x2F;digital game purchases) and platform subscription revenue (e.g. PS5 multiplayer SaaS).
So it&#x27;s unsurprising that the game shipped with anti-abuse countermeasures on day one.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;defense-forced-remote-wipe-on-connect&quot;&gt;&lt;span class=&quot;title-sub&quot;&gt;Defense&lt;&#x2F;span&gt;&lt;span class=&quot;title-separator&quot;&gt;:&lt;&#x2F;span&gt; Forced Remote Wipe on Connect&lt;&#x2F;h2&gt;
&lt;p&gt;While poking at edge cases for this post, I came across build-error-detection logic and a &lt;a href=&quot;..&#x2F;..&#x2F;images&#x2F;ac6_error_detection.jpg&quot;&gt;corresponding prompt UI&lt;&#x2F;a&gt; for forced remote wipe (no ability to opt-out if client is network-connected). To the best of my knowledge, this &quot;kill switch&quot; is only used for data either willingly deleted by the owner (e.g. original removed) or forcibly taken down by the developer (e.g. an inappropriate custom logo is reported, a content moderation team takes action).&lt;&#x2F;p&gt;
&lt;p&gt;This means FromSoftware already has production-tested capability for remote wipe &lt;em&gt;after&lt;&#x2F;em&gt; data hits disk, but not selective blocking &lt;em&gt;beforehand&lt;&#x2F;em&gt;.
Although simple and likely effective in practice, remote wipe has at least two significant drawbacks:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fallible&lt;&#x2F;strong&gt; - The client stores an invalid config locally and must connect to game servers to remediate. Locally-generated invalid builds are fully functional as long as the game is played offline. So the theoretical worst case exposure time is &lt;em&gt;indefinitely&lt;&#x2F;em&gt; long.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Especially on PC, where native code and network traffic can be instrumented by technical users. Software-only, client-side security controls are limited to &quot;best effort&quot; guarantees. For some applications, &quot;best effort&quot; isn&#x27;t &quot;good enough&quot;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Destructive&lt;&#x2F;strong&gt; - Remote build wipe is forced data loss. For any user who redeemed a share code, not just the user who knowingly bypassed the lock. The cost of defense includes widespread &quot;collateral damage&quot;.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;For many software services, data loss risks a permanent reputation hit and significant customer turnover.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;But let&#x27;s not miss the forest for the trees.
The FromSoft team shipped a smash hit, cross-platform game with few stability issues or technical glitches.
They&#x27;ve implemented a capability for emergency removal of objectionable content and have thus far managed to prevent &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gamerant.com&#x2F;call-of-duty-modern-warfare-3-cheating-increase-complaints&#x2F;&quot;&gt;multiplayer cheating&lt;&#x2F;a&gt;.
While the security industry all-too-often learns from embarrassing public failures, this post examines finer details in what is an unequivocal success - by any measure.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Any now-harmless, historical examples of usable insecurity in games?&lt;&#x2F;strong&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;YouTube channel &quot;Modern Vintage Gamer&quot; &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=uRB7iUCX4KQ&quot;&gt;announced a 23 year-old zero-day&lt;&#x2F;a&gt; for bypassing Sony PS1 game-disk DRM.
A movie-license game, released October 2000, included code to &quot;hot swap&quot; game discs.
That&#x27;s a common feature for multi-disk games of the CD era.
To continue game story&#x2F;progression while loading new assets from additional storage media.&lt;&#x2F;p&gt;
&lt;p&gt;Except this big-budget game had only 1 disc when it shipped.&lt;&#x2F;p&gt;
&lt;p&gt;The player enters a disk-swap debug mode if a special &quot;cheat code&quot; is manually input (think &quot;backdoor&quot;).
Enable this mode, swap the current&#x2F;official disk for any home-made copy of game B, and you&#x27;ve now launched game B.
No signature validation, no region lock.
Complete, usable &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;playlist?list=PLUbw0IXAmW2rMk5g19MrqcyebecSrrSeJ&quot;&gt;DRM unlock&lt;&#x2F;a&gt; for clients that won&#x27;t be patched.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;takeaway&quot;&gt;&lt;span class=&quot;title-sub&quot;&gt;Takeaway&lt;&#x2F;span&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;We explored a low-stakes but realistic &quot;usable insecurity&quot; case study.
No cheating or piracy involved.
Fully opt-in persistence.
We saw how any non-technical user could create and preserve an invalid state, via interaction of two factors:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Bug&lt;&#x2F;strong&gt; (edit lock bypass) - GUI-only flow to create a local, invalid configuration.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Feature&lt;&#x2F;strong&gt; (social sharing) - Official mechanism to sync configurations across clients.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Nothing but respect for FromSoftware - have been an AC fan since 3 back on the PS2.
This time it was all fun and [literally] games!
Anything worth extrapolating?&lt;&#x2F;p&gt;
&lt;p&gt;Complex systems are difficult to reason about.
Business logic often has exponential branching paths, e.g. &quot;state explosion&quot;.
So all real-world products ship with some non-zero number of bugs.&lt;&#x2F;p&gt;
&lt;p&gt;Most systems can be patched after bugs are discovered.
But patching is non-trivial for complex systems and&#x2F;or large populations.
And when the technical barrier to system subversion is low, any client can become uncooperative.
Sometimes coordinated entities can systematically degrade patching capability by increasing its cost.
Leveraging unexpected &lt;strong&gt;bug-bug&lt;&#x2F;strong&gt;, &lt;strong&gt;bug-feature&lt;&#x2F;strong&gt;, or even &lt;strong&gt;feature-feature&lt;&#x2F;strong&gt; composition.&lt;&#x2F;p&gt;
&lt;p&gt;So it&#x27;s best to fix bugs - especially the subset that are exploitable vulnerabilities - before shipping.
Instead of attempting to put out the fires [of Rubicon].
Doubly true for &quot;usable vulnerabilities&quot;, those reliable for low-skill attackers.
Prevention isn&#x27;t always possible but tends to minimize tradeoffs when it is.&lt;&#x2F;p&gt;
&lt;p&gt;Thus - assuming an architecture&#x2F;design process already succeeded - we should invest in:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Automated and Manual Testing&lt;&#x2F;strong&gt; - Maybe unit tests asserting on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Model%E2%80%93view%E2%80%93viewmodel&quot;&gt;view-models&lt;&#x2F;a&gt; returned from functions could have caught the AC6 bug. When &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tiemoko.com&#x2F;blog&#x2F;diff-fuzz&#x2F;&quot;&gt;automated tests&lt;&#x2F;a&gt; are infeasible, both &lt;em&gt;exploratory&lt;&#x2F;em&gt; (e.g. pre-merge code review) and &lt;em&gt;structured&lt;&#x2F;em&gt; (e.g. pre-release QA testing) manual effort is exceptionally valuable. Sure - detecting certain flaws, like memory-safety violations, is best left to tools. But in the general case human smarts can find defects automation won&#x27;t. At scale, repeatable processes can harness those smarts.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Formal Verification&lt;&#x2F;strong&gt; - Limited, but important, classes of problems can be defined out of existence. Maybe a menu design based on &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;cliffle.com&#x2F;blog&#x2F;rust-typestate&#x2F;&quot;&gt;Rust&#x27;s type-state pattern&lt;&#x2F;a&gt; could enable provably correct lock state. If invalid states could cause damage to property or loss of human life, it&#x27;s wise to guide implementation with a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;lamport.azurewebsites.net&#x2F;tla&#x2F;industrial-use.html&quot;&gt;formal model of the intended system&lt;&#x2F;a&gt; and&#x2F;or &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;verus-lang&#x2F;verus&quot;&gt;use machine-checked annotations&lt;&#x2F;a&gt; to validate functional correctness of the code itself. Unlike testing, verification can prove the absence of certain bugs (within some bounds, e.g. micro-architectural attacks typically out-of-scope).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Security matters when the next breach might be &quot;game over&quot;.
Good luck out there.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;02-22-2024 update: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.bandainamcoent.eu&#x2F;armored-core&#x2F;news&#x2F;armored-core-vi-fires-of-rubicon-patch-notes-106&quot;&gt;1.06 patch notes&lt;&#x2F;a&gt;, released 02-05-2024, include &quot;Fixed a bug with AC data uploaded to the game server, where if the data was loaded and then deleted from the game server, the loaded data would be reverted to default paint and decals&quot;. We previously triggered this bug to capture the &lt;a href=&quot;..&#x2F;..&#x2F;images&#x2F;ac6_error_detection.jpg&quot;&gt;&quot;kill switch&quot; UI screenshot&lt;&#x2F;a&gt; linked in discussion of defense. Given this fix, assume the kill switch is only for forced removal. Post text remains unedited, both share codes are still active, the focal bypass still works in 1.06!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Read a free technical book!&lt;&#x2F;strong&gt;
I&#x27;m fulfilling a lifelong dream and writing a book.
It&#x27;s about developing secure and robust systems software.
Although a work-in-progress, the book is freely available online (no paywalls or obligations):
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;highassurance.rs&#x2F;&quot;&gt;https:&#x2F;&#x2F;highassurance.rs&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Technical Time Travel: On Vintage Programming Books</title>
        <published>2022-01-29T00:00:00+00:00</published>
        <updated>2022-01-29T00:00:00+00:00</updated>
        <rights type="html">&amp;copy; 2020-2025 Tiemoko Ballo</rights>
        
        <author>
          <name>
            
              Tiemoko Ballo
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tiemoko.com/blog/vintage-tech-books/"/>
        <id>https://tiemoko.com/blog/vintage-tech-books/</id>
        
        <content type="html" xml:base="https://tiemoko.com/blog/vintage-tech-books/">&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;01-31-2022 update: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;programming&#x2F;comments&#x2F;sfl0jt&#x2F;technical_time_travel_on_vintage_programming_books&#x2F;&quot;&gt;Reddit discussion here&lt;&#x2F;a&gt;. &quot;The Mythical Man-Month&quot; by Frederick Brooks (1975) was highly recommended!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;03-20-2022 update: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=30697697&quot;&gt;Hacker News discussion here&lt;&#x2F;a&gt;. Interesting perspectives and vintage recommendations.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;As technologists, we&#x27;re constantly gulping from the bleeding-edge firehose: new versions, new standards, new frameworks, new paradigms.
This is largely a good thing.
Most advances offer a tangible improvement over the status quo.
Specialization (e.g. recent &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.cmu.edu&#x2F;news&#x2F;stories&#x2F;archives&#x2F;2018&#x2F;may&#x2F;ai-undergraduate-degee.html&quot;&gt;Bachelors Degrees in AI&lt;&#x2F;a&gt;) speeds the advance of promising fields, it&#x27;s a future of exciting possibility.
So long as our eager technology can be &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;undark.org&#x2F;2020&#x2F;10&#x2F;16&#x2F;book-review-ai-in-the-wild&#x2F;&quot;&gt;guided by effective policy&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;What if we turn that lens backward, toward the yesteryear innovations of our shared past?
Not in an effort to gain some competitive edge in the present - although the insight of historical context can be piercing - but simply to satisfy intellectual curiosity.
To scratch that innocent itch for understanding how things work.
Or, given hindsight, why they didn&#x27;t.&lt;&#x2F;p&gt;
&lt;p&gt;To this end, I enjoy collecting rare and vintage programming books.
It&#x27;s not a hobby that leads to party invitations.
But it is surprisingly cheap (the demand for used and outdated technical references is small).
And mildly satisfying.
There&#x27;s just something quaint about pre-internet computer books, with their dead-tree print editions and crude typesetting.
Each offering an alluring nostalgia, somehow palatable even if the era is before your own.&lt;&#x2F;p&gt;
&lt;p&gt;This post shares three of my favorites and summarizes the historical backdrop for each.
All three have ties to modern-day tech, so I hope you&#x27;ll find some aspect informative or interesting.
Hit the gas until &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;DeLorean_time_machine&quot;&gt;88 MPH&lt;&#x2F;a&gt;, we&#x27;re going back Marty!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-debugging-with-gdb-by-richard-stallman-et-al-1988-present&quot;&gt;&lt;span class=&quot;title-sub&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;title-separator&quot;&gt;)&lt;&#x2F;span&gt; &lt;em&gt;Debugging with GDB&lt;&#x2F;em&gt; by Richard Stallman et al. &lt;span class=&quot;title-separator&quot;&gt;(1988 - Present)&lt;&#x2F;span&gt;&lt;&#x2F;h2&gt;
&lt;br&gt;
&lt;p align=&quot;center&quot;&gt;
  &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;book_gdb.jpg&quot; alt=&quot;Debugging with GDB (1988 - Present)&quot; style=&quot;width:100%&quot;&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Having done &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;tiemoko.com&#x2F;publications&#x2F;asia_ccs_2021_sok_enabling_security_analyses_of_embedded_systems_via_rehosting.pdf&quot;&gt;academic research&lt;&#x2F;a&gt; in dynamic program analysis, I have something of a soft spot for debuggers and emulators.
The 1st edition of the long-running &quot;Debugging with GDB&quot; series was copyrighted in 1988.
In fitting Free Software Foundation (FSF) fashion, the most current edition is &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.sourceware.org&#x2F;gdb&#x2F;current&#x2F;onlinedocs&#x2F;gdb.html&quot;&gt;freely available&lt;&#x2F;a&gt; online.
It&#x27;s &lt;em&gt;the&lt;&#x2F;em&gt; comprehensive reference for &lt;code&gt;gdb&lt;&#x2F;code&gt; - a userland debugger supporting Unix-like systems.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;gdb&lt;&#x2F;code&gt; is a cornerstone of the incredibly influential &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;GNU_toolchain&quot;&gt;GNU toolchain&lt;&#x2F;a&gt;.
This toolchain includes, among others, the &lt;code&gt;gcc&lt;&#x2F;code&gt; compiler, the &lt;code&gt;glibc&lt;&#x2F;code&gt; C standard library, and the &lt;code&gt;make&lt;&#x2F;code&gt; build system - software fundamental to both the rise of the Linux kernel and systems programming in general.
Because GNU technologies are so ubiquitous on the server-side, almost all of your daily computer use is, in some direct or indirect way, enabled by GNU utilities.
This handful of tools annually generates &lt;em&gt;billions&lt;&#x2F;em&gt; of dollars in value.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Richard_Stallman&quot;&gt;Dr. Richard Stallman&lt;&#x2F;a&gt;, the original author of several GNU programs, personally signed this 2010 copy when I met him at a software conference in 2016.
I distinctly remember people getting up and walking out halfway through his conference-closing keynote, which espoused the exploitative nature of cloud services.
Categorically.
Any and all usage of remote machines running code managed by another party.
Though no doubt an icon of computing, Stallman could be described as an &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.washingtonpost.com&#x2F;education&#x2F;2019&#x2F;09&#x2F;17&#x2F;computer-scientist-richard-stallman-resigns-mit-after-comments-about-epstein-scandal&#x2F;&quot;&gt;abrasive speaker&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;While Stallman&#x27;s grandiose vision for collective ownership of all software did not come to pass, it certainly left a mark.
Today&#x27;s open ecosystems are likely a result of the FSF shifting our &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Overton_window&quot;&gt;Overton window&lt;&#x2F;a&gt;.
And we&#x27;re all reaping the benefits.
Daily.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Classic Problems, Modern Solutions&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.sourceware.org&#x2F;gdb&#x2F;&quot;&gt;&lt;code&gt;gdb&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&#x2F;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rr-project.org&#x2F;&quot;&gt;&lt;code&gt;rr&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is one of the few late 80s developer tools still popular today.
With forward and reverse engineers alike, nonetheless.
Perhaps it&#x27;s unsurprising that several recent startups ship debugging and observability products.
The Total Addressable Market (TAM) for a timeless need is sizable.&lt;&#x2F;p&gt;
&lt;p&gt;Some of these startups include (listed alphabetically, non-exhaustive, and &lt;em&gt;not&lt;&#x2F;em&gt; an endorsement of any products):
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;logrocket.com&#x2F;features&#x2F;&quot;&gt;logrocket.com&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.metawork.com&#x2F;&quot;&gt;metawork.com&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.replay.io&#x2F;&quot;&gt;replay.io&lt;&#x2F;a&gt;, and &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.tetrane.com&#x2F;&quot;&gt;tetrane.com&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;2-bios-interface-technical-reference-by-ibm-1987&quot;&gt;&lt;span class=&quot;title-sub&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;title-separator&quot;&gt;)&lt;&#x2F;span&gt; &lt;em&gt;BIOS Interface Technical Reference&lt;&#x2F;em&gt; by IBM &lt;span class=&quot;title-separator&quot;&gt;(1987)&lt;&#x2F;span&gt;&lt;&#x2F;h2&gt;
&lt;br&gt;
&lt;p align=&quot;center&quot;&gt;
  &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;book_bios.jpg&quot; alt=&quot;Personal System&#x2F;2 and Personal Computer BIOS Interface Technical Reference (1987)&quot; style=&quot;width:100%&quot;&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Clean_room_design&quot;&gt;&quot;Clean-room design&quot;&lt;&#x2F;a&gt; was an underhanded way to legally reverse engineer and clone a competitor&#x27;s product.
It works like this: engineer A produces a specification after studying the competing product, a lawyer signs off on the spec not including copyrighted material, and engineer B re-implements the product from the spec A created.
A and B have the same employer, but since they&#x27;re not the same person there&#x27;s &lt;em&gt;technically&lt;&#x2F;em&gt; no copyright infringement.
This technique was used during the fiercely-competitive market rush of early personal computing.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps its most infamous application was the recreation of IBM&#x27;s Basic Input-Output System (BIOS).
IBM&#x27;s Personal Computer (PC) introduced home computing to an entire generation, ushering in a new era.
It catalyzed mainstream adoption of general-purpose computers, which had largely been corporate tools and hobbyist curiosities.
By reverse engineering its BIOS, a piece of low-level firmware, competitors could reduce time-to-market for software-compatible clones of IBM&#x27;s flagship consumer product.&lt;&#x2F;p&gt;
&lt;p&gt;That&#x27;s exactly what successful companies like &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.allaboutcircuits.com&#x2F;news&#x2F;how-compaqs-clone-computers-skirted-ibms-patents-and-gave-rise-to-eisa&#x2F;&quot;&gt;Compaq Computer&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;books.google.com&#x2F;books?id=Bwng8NJ5fesC&amp;amp;lpg=PA6&amp;amp;pg=PA56#v=onepage&amp;amp;q&amp;amp;f=false&quot;&gt;Phoenix Technologies&lt;&#x2F;a&gt; did.
One team obtained IBM technical manuals, likely very similar to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;bitsavers.trailing-edge.com&#x2F;pdf&#x2F;ibm&#x2F;pc&#x2F;ps2&#x2F;PS2_and_PC_BIOS_Interface_Technical_Reference_Apr87.pdf&quot;&gt;the book pictured above&lt;&#x2F;a&gt;, and wrote specifications that described program behavior without including any of the book&#x27;s code.
Another team wrote a BIOS clone compliant with the specs, likely in assembly language, and then ran PC software atop the replica to check that it functioned as intended.
Unethical?
Probably.
Effective?
Definitely.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Dominance via Interoperability&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Almost all modern laptops&#x2F;desktops&#x2F;servers are direct descendants of the 1981 IBM PC, and use an updated version of its x86 architecture.
It&#x27;s a legacy of enduring monoculture.
So why did the PC dominate so convincingly?&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps because it was a break from tradition for Big Blue, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;adventofcomputing.libsyn.com&#x2F;episode-51-the-ibm-pc&quot;&gt;Sean Haas posits&lt;&#x2F;a&gt;.
Whereas the company&#x27;s mainframe machines used a proprietary tech stack, the PC was open and modular, readily supporting 3rd-party hardware and software.
Its design team prioritized both time-to-market and production capacity by intentionally mating mass-produced 8-bit peripherals to their 16-bit CPU (a variant of the venerable Intel 8086).
Had different choices been made, maybe Apple&#x27;s recent &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Apple_M1&quot;&gt;ARM SoC&lt;&#x2F;a&gt; wouldn&#x27;t be so notable an exception to the x86 rule.&lt;&#x2F;p&gt;
&lt;p&gt;BIOS may have been sunset in favor of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;uefi.org&#x2F;specifications&quot;&gt;UEFI&lt;&#x2F;a&gt;, but the 8086 CPU refuses to die.
To this day, your brand new 64-bit x86 PC or console will boot into &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;wiki.osdev.org&#x2F;Real_Mode&quot;&gt;&quot;real-mode&quot;&lt;&#x2F;a&gt; on startup - ready to execute 16-bit instructions with a whopping 1MB of addressable memory.
It&#x27;s a strange bit of technical debt, an artifact of a 40-year commitment to backward compatibility.
And likely to be around for 40 more.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;3-the-ada-reference-manual-by-honeywell-1983&quot;&gt;&lt;span class=&quot;title-sub&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;title-separator&quot;&gt;)&lt;&#x2F;span&gt; &lt;em&gt;The Ada Reference Manual&lt;&#x2F;em&gt; by Honeywell &lt;span class=&quot;title-separator&quot;&gt;(1983)&lt;&#x2F;span&gt;&lt;&#x2F;h2&gt;
&lt;br&gt;
&lt;p align=&quot;center&quot;&gt;
  &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;book_ada.jpg&quot; alt=&quot;Reference Manual for the Ada Programming Language (1983)&quot; style=&quot;width:100%&quot;&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;In the late 70s, the US Department of Defense (DoD) had a critical problem: their embedded systems projects used &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ocw.mit.edu&#x2F;courses&#x2F;aeronautics-and-astronautics&#x2F;16-01-unified-engineering-i-ii-iii-iv-fall-2005-spring-2006&#x2F;comps-programming&#x2F;15_robertdewar.pdf&quot;&gt;over 450 esoteric programming languages&lt;&#x2F;a&gt;, maintenance was a multi-billion dollar burden.
The government&#x27;s answer? Standardization.
Create a new language specially tailored to safety-critical embedded systems and legally mandate its use for applicable projects.&lt;&#x2F;p&gt;
&lt;p&gt;In 1978, the DoD put forth the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20200914235620&#x2F;https:&#x2F;&#x2F;dwheeler.com&#x2F;steelman&#x2F;steelman.htm&quot;&gt;&quot;Steelman&quot; requirements list&lt;&#x2F;a&gt; and sponsored a competition (not unlike the more contemporary &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.darpa.mil&#x2F;news-events&#x2F;2014-03-13&quot;&gt;DARPA &quot;Grand Challenges&quot;&lt;&#x2F;a&gt;).
Four language design teams entered the fray: red, green, blue, and yellow.
The green team won and produced the above &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;archive.adaic.com&#x2F;standards&#x2F;83lrm&#x2F;html&#x2F;lrm-TOC.html&quot;&gt;language specification&lt;&#x2F;a&gt;, hence the binding color.
This one is a commemorative copy with a forward thanking the original Honeywell development team.&lt;&#x2F;p&gt;
&lt;p&gt;Their language was named &quot;Ada&quot;, after &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Ada_Lovelace&quot;&gt;Ada Lovelace&lt;&#x2F;a&gt; - a pioneering programmer who debugged her yet-to-be-built &lt;em&gt;mechanical&lt;&#x2F;em&gt; computer via mail correspondence.
The spec&#x27;s official document number, MIL-STD-1815-A, includes Lovelace&#x27;s 1815 birthdate.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;On Modern Ada&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Today&#x27;s Ada boasts impressive features rarely seen in other programming languages.
Including range types (encoding valid ranges of values at the type system level) and, for the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;SPARK_(programming_language)&quot;&gt;SPARK&lt;&#x2F;a&gt; subset, deductive verification (hand-written &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Hoare_logic&quot;&gt;Hoare logic&lt;&#x2F;a&gt; specifications, proven via &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;people.eecs.berkeley.edu&#x2F;~sseshia&#x2F;pubdir&#x2F;SMT-BookChapter.pdf&quot;&gt;SMT solving&lt;&#x2F;a&gt; at compile-time).&lt;&#x2F;p&gt;
&lt;p&gt;SPARK Ada has made &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.adacore.com&#x2F;uploads&#x2F;techPapers&#x2F;Safe-Dynamic-Memory-Management-in-Ada-and-SPARK.pdf&quot;&gt;recent advances&lt;&#x2F;a&gt; in heap memory verification.
Nvidia chose it &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=2YoPoNx3L5E&quot;&gt;over Rust for low-level firmware&lt;&#x2F;a&gt; in 2019 - citing Rust&#x27;s &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ferrous-systems.com&#x2F;blog&#x2F;ferrocene-update-three-the-road&#x2F;&quot;&gt;lack of certification&lt;&#x2F;a&gt; for safety-critical systems as one consideration.
But Ada hasn&#x27;t quite taken off in the mainstream.
Social factors - perhaps association with restrictive licenses and a proprietary compiler - have constrained adoption.
Which is a shame, the language&#x27;s feature set remains compelling.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;closing-thoughts&quot;&gt;&lt;span class=&quot;title-sub&quot;&gt;Closing Thoughts&lt;&#x2F;span&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;What we think of as digital antiquity is, within the timescale of human existence, too recent to truly warrant the label &quot;history&quot;.
There are Ada early-adopters still employed as developers today.
The GNU General Public License (GPL) is still chosen for new projects.
As a child of the 90s, I have fond memories of the American Megatrends BIOS clone splash screen - illuminated via the fuzzy glow of a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Cathode-ray_tube&quot;&gt;CRT&lt;&#x2F;a&gt; monitor.&lt;&#x2F;p&gt;
&lt;p&gt;The pace of technological progress is blistering.
And its vector is unpredictable.
Studying the past doesn&#x27;t necessarily make it easier to foresee the future.
It may, however, provide richer context for some of today&#x27;s technologies.
Or maybe just today&#x27;s technical debt.
Either way, our current state-of-the-art will soon be a retro curiosity relegated to a used book bargain bin.
Hopefully for the better.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Read a free technical book!&lt;&#x2F;strong&gt;
I&#x27;m fulfilling a lifelong dream and writing a book.
It&#x27;s about developing secure and robust systems software.
Although a work-in-progress, the book is freely available online (no paywalls or obligations):
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;highassurance.rs&#x2F;&quot;&gt;https:&#x2F;&#x2F;highassurance.rs&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Beyond the Borrow Checker: Differential Fuzzing</title>
        <published>2022-01-04T00:00:00+00:00</published>
        <updated>2022-01-04T00:00:00+00:00</updated>
        <rights type="html">&amp;copy; 2020-2025 Tiemoko Ballo</rights>
        
        <author>
          <name>
            
              Tiemoko Ballo
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tiemoko.com/blog/diff-fuzz/"/>
        <id>https://tiemoko.com/blog/diff-fuzz/</id>
        
        <content type="html" xml:base="https://tiemoko.com/blog/diff-fuzz/">&lt;hr &#x2F;&gt;
&lt;p align=&quot;center&quot;&gt;
  &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;openssl_x509_coverage_growth.svg&quot; alt=&quot;Coverage growth chart from openssl_x509, from Google&#x27;s Fuzz Bench&quot; style=&quot;width:100%&quot;&gt;
  &lt;figcaption&gt;&lt;i&gt;&lt;center&gt;Image source: Google&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;www.fuzzbench.com&#x2F;reports&#x2F;2021-06-02&#x2F;index.html#openssl_x509-summary&quot;&gt;FuzzBench project.&lt;&#x2F;a&gt; Note coverage for the OpenSSL target tapers off rather quickly.&lt;&#x2F;center&gt;&lt;&#x2F;i&gt;&lt;&#x2F;figcaption&gt;
&lt;&#x2F;p&gt;
&lt;br&gt;
&lt;p&gt;The oft-cited &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Infinite_monkey_theorem&quot;&gt;&quot;infinite monkey theorem&quot;&lt;&#x2F;a&gt; states that a monkey hitting utterly random keys on a typewriter will, given infinite time, manage to write the complete works of Shakespeare.
That&#x27;s an offensively inefficient way to reproduce classic literature.
But what if your goal is to justify confidence in the correctness of a program which &lt;em&gt;parses&lt;&#x2F;em&gt; Shakespearean English?
In a cruel twist of fate fitting of the source material: a probabilistic technique is actually one of your best options.&lt;&#x2F;p&gt;
&lt;p&gt;Repeatedly subjecting programs to randomized and malformed inputs, aka &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;1812.00140.pdf&quot;&gt;&quot;fuzzing&quot; (Manes et al.)&lt;&#x2F;a&gt;, is an influential idea in software testing because, plainly, it works.
Coverage-guided fuzzing, a modern variation that makes our dutiful monkeys &quot;smarter&quot;, is a &lt;em&gt;largely automated&lt;&#x2F;em&gt; analysis capable of discovering critical vulnerabilities.
Especially in programs written in memory-unsafe languages.
Yet, despite the availability of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;AFLplusplus&#x2F;AFLplusplus&quot;&gt;free production-grade fuzzers&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lcamtuf.coredump.cx&#x2F;afl&#x2F;&quot;&gt;their respective trophy cases of real-world bugs&lt;&#x2F;a&gt;, the technique remains criminally under-utilized in the mainstream.&lt;&#x2F;p&gt;
&lt;p&gt;We&#x27;ll start with big-picture concepts, transition to sobering truths about peer-reviewed fuzzing research, then walk through a real-world &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;llvm.org&#x2F;docs&#x2F;LibFuzzer.html&quot;&gt;&lt;code&gt;libFuzzer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; &quot;harness&quot; for a public Rust library (think unit test snippet, but for configuring a fuzzing campaign).
Since we&#x27;re targeting safe Rust code, we&#x27;ll use &lt;em&gt;differential fuzzing&lt;&#x2F;em&gt; to demonstrate that a 3rd-party container implementation is comparable to the standard library in reliability and correctness.
As opposed to fuzzing for memory corruption bugs the borrow checker &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;tiemoko.com&#x2F;blog&#x2F;blue-team-rust&#x2F;&quot;&gt;already protects us from&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;My hope is that, armed with background knowledge and a couple of code snippets, you can make informed decisions about fuzzing in the context of software assurance - or maybe even add a harness to your next project.
Note &lt;code&gt;libFuzzer&lt;&#x2F;code&gt; readily supports C and C++, where memory safety errors are always in scope, and our high-level methodology is transferable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;give-it-to-me-straight&quot;&gt;Give it to me straight&lt;&#x2F;h2&gt;
&lt;p&gt;Before we delve into the nitty-gritty tactics, let&#x27;s talk strategy - what you need to know as a decision maker.
Fuzzing is a dynamic program analysis with the following characteristics:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;No false positives:&lt;&#x2F;strong&gt; All results are real bugs.
&lt;ul&gt;
&lt;li&gt;Even if they&#x27;re not always exploitable vulnerabilities.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;High false negatives:&lt;&#x2F;strong&gt; Many, if not most, bugs are missed.
&lt;ul&gt;
&lt;li&gt;For reasons more complex than lack of code coverage (e.g. execution state-space not correlated with branches alone).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Unbounded yield saturation:&lt;&#x2F;strong&gt; &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;blog.regehr.org&#x2F;archives&#x2F;1796&quot;&gt;Groce and Reghr explain&lt;&#x2F;a&gt; why fuzzing&#x27;s Return On Investment (ROI) subsides:
&lt;ul&gt;
&lt;li&gt;Expected returns diminish according to a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Power_law&quot;&gt;power law distribution&lt;&#x2F;a&gt; given constant compute resources.&lt;&#x2F;li&gt;
&lt;li&gt;Discovering more of a given bug class may be &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mboehme.github.io&#x2F;paper&#x2F;FSE20.EmpiricalLaw.pdf&quot;&gt;linearly correlated (Bohme et al.)&lt;&#x2F;a&gt; with compute resource investment.&lt;&#x2F;li&gt;
&lt;li&gt;Discovering bugs of &lt;em&gt;linearly&lt;&#x2F;em&gt; more diverse bug classes may require &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mboehme.github.io&#x2F;paper&#x2F;FSE20.EmpiricalLaw.pdf&quot;&gt;&lt;em&gt;exponentially&lt;&#x2F;em&gt; more (Bohme et al.)&lt;&#x2F;a&gt; investment.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;All recent advances in fuzzing attempt to address the latter two shortcomings, false negatives and saturation.
How they do so varies wildly: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;users.ece.cmu.edu&#x2F;~sangkilc&#x2F;papers&#x2F;ccs13-woo.pdf&quot;&gt;mutation scheduling (Woo et al.)&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;system&#x2F;files&#x2F;sec19-blazytko.pdf&quot;&gt;input grammars (Blazytko et al.)&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ieeexplore.ieee.org&#x2F;stamp&#x2F;stamp.jsp?tp=&amp;amp;arnumber=8835316&quot;&gt;coverage-guidance (Nagy et al.)&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;system&#x2F;files&#x2F;conference&#x2F;usenixsecurity18&#x2F;sec18-yun.pdf&quot;&gt;concolic execution (Yun et al.)&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;system&#x2F;files&#x2F;sec20-gan.pdf&quot;&gt;dynamic taint analysis (Gan et al.)&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.ndss-symposium.org&#x2F;wp-content&#x2F;uploads&#x2F;2020&#x2F;02&#x2F;23096-paper.pdf&quot;&gt;performance optimization (Schumilo et al.)&lt;&#x2F;a&gt;, etc.&lt;&#x2F;p&gt;
&lt;p&gt;In the broader picture of a wholistic software security initiative, it&#x27;s worth noting:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dynamic testing is only half of the story:&lt;&#x2F;strong&gt; Static security analyses, namely static taint analysis and certain variants of abstract interpretation, offer a complimentary set of strengths (e.g. ability to reason about all possible executions) at the cost of unique weaknesses (e.g. over-approximation and false positives). You shouldn&#x27;t place all your eggs in the runtime basket.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rust democratizes advanced static analysis:&lt;&#x2F;strong&gt; Temporal memory safety (e.g. no heap or concurrency bugs) is guaranteed at compile-time. Spatial memory safety (e.g. no buffer overflow) is run-time enforced, only where necessary. This combo enables &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.eurekalert.org&#x2F;news-releases&#x2F;610682&quot;&gt;provable&lt;&#x2F;a&gt; safety without expensive products (like licensed code analysis tools) or hard-to-scale expert processes (like code review by skilled security engineers). So long as the developer can satisfy ownership constraints.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fuzzing favors compiled binaries:&lt;&#x2F;strong&gt; Fuzzers have traditionally excelled at finding low-level failures in native code (e.g. executed directly by the CPU, like C&#x2F;C++&#x2F;Rust). That&#x27;s the focus of this post. The bulk of relevant advances serve this niche.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The future of fuzzing is in flux:&lt;&#x2F;strong&gt; An average organization likely writes more web applications than web servers, so fuzzing of both managed code (e.g. interpreted or run in a VM, like Python&#x2F;Java&#x2F;TypeScript) and web APIs (see &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mayhem4api.forallsecure.com&#x2F;docs&#x2F;&quot;&gt;Mayhem4API&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;microsoft&#x2F;restler-fuzzer&quot;&gt;RESTler&lt;&#x2F;a&gt;) is increasingly relevant in industry.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now that we have some bearing in the space, let&#x27;s look at the frontier.
Where the optimistic promises of the theoretical meet the crushing pressures of the practical: applied research.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;are-state-of-the-art-fuzzers-just-monkeying-around&quot;&gt;Are state-of-the-art fuzzers just monkeying around?&lt;&#x2F;h2&gt;
&lt;p&gt;Yes and no.
An honest answer requires nuance.
Advances in &quot;gray-box&quot; techniques, coverage-guidance in particular, catalyzed a leap forward in the efficacy of practical fuzzers.
Yet, despite dozens of top-tier publications and awarded PhDs, our subsequent progress hasn&#x27;t proven empirically reliable.
A surprising fraction of peer-reviewed algorithms aren&#x27;t convincingly robust in practice.&lt;&#x2F;p&gt;
&lt;p&gt;Before we bear the bad news, we should cover the good: evolutionary algorithms.
Gray-box fuzzers leverage lightweight instrumentation to collect limited information about program internals during a run.
After employing various techniques to measure program &lt;em&gt;coverage&lt;&#x2F;em&gt; (e.g. basic block control flow edges traversed), some gray-box fuzzers prioritize mutation of specific inputs in an effort to maximize said coverage.
This strategy, dubbed &quot;evolutionary fuzzing&quot;, tunes test populations via some notion of &quot;fitness&quot; - borrowing ideas from &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Genetic_algorithm&quot;&gt;genetic algorithms&lt;&#x2F;a&gt; to generate more potent test cases.
The efficacy can be shocking.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lcamtuf.coredump.cx&#x2F;afl&#x2F;&quot;&gt;American Fuzzy Lop (AFL)&lt;&#x2F;a&gt; was &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.blackhat.com&#x2F;presentations&#x2F;bh-usa-07&#x2F;DeMott_Enbody_and_Punch&#x2F;Whitepaper&#x2F;bh-usa-07-demott_enbody_and_punch-WP.pdf&quot;&gt;not the first&lt;&#x2F;a&gt; evolutionary fuzzer.
But it&#x27;s popularity makes it very much an integral part of the security community&#x27;s zeitgeist, circa 2014 to present.
AFL&#x27;s coverage-hungry algorithms famously demonstrated &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lcamtuf.blogspot.com&#x2F;2014&#x2F;11&#x2F;pulling-jpegs-out-of-thin-air.html&quot;&gt;iteratively generating a valid JPEG&lt;&#x2F;a&gt; from scratch.
Inputs generated by a traditional &quot;black-box&quot; (e.g. no knowledge of program internals) fuzzer would have continually failed a check early in header parsing, never exercising the majority of a JPEG library&#x27;s logic.
AFL could infer the relationship between a library&#x27;s input and its control flow - well enough to pass checks of validity.&lt;&#x2F;p&gt;
&lt;p&gt;To put an abstract spin on it: evolutionary fuzzing can force a small subset of state transitions in the target program&#x27;s automata.
See more states, find more security-relevant edge cases.&lt;&#x2F;p&gt;
&lt;p&gt;Now for the hard truth.
AFL still falls victim to the aforementioned false positive and saturation problems.
In the grand scheme of things, the JPEG example is a parlor trick for which evolutionary algorithms are particularly well-suited.
Fuzzing coverage &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.fuzzbench.com&#x2F;reports&#x2F;2021-06-02&#x2F;index.html#openssl_x509-summary&quot;&gt;tapers logarithmically&lt;&#x2F;a&gt; in many real-world programs without meaningful results.
The evolution stops, the fuzzer gets stuck.
Moreover, there exists peer-reviewed research arguing that we haven&#x27;t gotten markedly better at fuzzing since AFL&#x27;s 2014 debut. Two [cherry-picked] findings from that line of inquiry:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Much of fuzzing research is biased and difficult to replicate.&lt;&#x2F;strong&gt;
In a stern critique of contemporary work, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;pdf&#x2F;1808.09700.pdf&quot;&gt;Klees et al. (2018)&lt;&#x2F;a&gt; evaluated 32 fuzzing research papers - some of which used AFL as a baseline and claimed to develop improved fuzzers.
The evaluation found serious problems in the experimental design of every surveyed paper.
This implies each paper&#x27;s conclusions are unreliable at best and actively misleading at worst.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No fuzzer, regardless of sophistication, is convincingly superior.&lt;&#x2F;strong&gt;
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;system&#x2F;files&#x2F;sec21summer_li-yuwei.pdf&quot;&gt;Li et al. (2021)&lt;&#x2F;a&gt; developed a framework for metrics-based evaluation of modern fuzzers.
Their open-source, head-to-head comparison of 35 state-of-the-art fuzzers found no clear winner.
Judging by the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Mann%E2%80%93Whitney_U_test&quot;&gt;Mann-Whitney test&lt;&#x2F;a&gt; for unique bug counts, no fuzzer beat AFL across all real-world programs.
Not even contenders leveraging concolic execution, a technique often touted as the holy grail of software testing.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In essence, we&#x27;re still beholden to the fickle whims of chance, still just bashing keys on that metaphorical typewriter.
Fuzzing is an expensive waste of resources past some specific point in time.
And nobody yet knows how to reliably determine what that point is, that&#x27;s &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;dl.acm.org&#x2F;doi&#x2F;10.1145&#x2F;3339836&quot;&gt;an area of study (Tramontana et al.)&lt;&#x2F;a&gt; in itself.
Much like any research thrust, fuzzing aims to repeat and quantify phenomena we don&#x27;t fully understand.
It&#x27;s a pursuit closer to alchemy than chemistry.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;yikes-how-can-i-action-this-information&quot;&gt;Yikes. How can I action this information?&lt;&#x2F;h2&gt;
&lt;p&gt;One interpretation of these findings is that we have numerous monkeys each targeting different low-hanging fruit, modulo some overlap.
While that&#x27;s somewhat disheartening, we can double down on what works - evolutionary algorithms - and accept the limitations.
At least until the periodic wave of innovation graces us with another crest.
You can still get considerable value via one or more of the below strategies:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Low-effort, majority return:&lt;&#x2F;strong&gt; Use a mature coverage-guided fuzzer, if not doing so already.
&lt;ul&gt;
&lt;li&gt;Power law expected yield.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;High-effort, supplemental return:&lt;&#x2F;strong&gt; Use multiple fuzzers to increase bug yield, if compute budget allows.
&lt;ul&gt;
&lt;li&gt;Still power law yield, but higher bug totals on the Y-axis.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Continuous effort, continuous return:&lt;&#x2F;strong&gt; &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;forum.tezosagora.org&#x2F;t&#x2F;how-we-utilized-fuzzing-to-improve-security-in-the-tezedge-node&#x2F;3122&quot;&gt;Integrate a fuzzer into CI&lt;&#x2F;a&gt; and continually harness newly added interfaces.
&lt;ul&gt;
&lt;li&gt;Likely linear yield? Assuming your team&#x27;s secure coding skills have plateaued (both bug-rate and harnessing prowess).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;So several typewriters are better than one, but be sure you&#x27;ve tried bashing at least one set of keys before you ship a product.
New entry point for untrusted input appeared in code review?
Ideal time to add a new harness.
If a motivated attacker is the first person to fuzz your APIs...well that might reduce the universe of infinite possibilities down to a select few your Public Relations (PR) team won&#x27;t be happy about.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;that-s-a-cop-out-answer-we-can-do-better&quot;&gt;That&#x27;s a cop out answer. We can do better!&lt;&#x2F;h2&gt;
&lt;p&gt;When a solution to a hard problem can&#x27;t be reliably automated, we can fall back to augmenting human ability.
As a Rust programmer, you&#x27;ve already been half of a human-in-the-loop property verification system.
Those lifetime annotations &lt;code&gt;rustc&lt;&#x2F;code&gt; complains about?
They&#x27;re aiding an interprocedural static analysis.
By occasionally querying your genius meat-brain for them, the compiler solves an otherwise intractable problem: eliminating memory errors.&lt;&#x2F;p&gt;
&lt;p&gt;If carefully constructed, a harness is to a fuzzer what source annotations are to a static analyzer: a much-needed means by which to bridge the semantic gap.
One particularly powerful harnessing technique is &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Differential_testing&quot;&gt;&quot;differential fuzzing&quot;&lt;&#x2F;a&gt; - providing the same input to multiple programs and observing differences in their behavior.
This doesn&#x27;t change the fundamental calculus of the technique (no false positives, high false negatives, saturation).
But it does provide richer results, enabling detection of higher-level logical errors &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;yossarian.net&#x2F;res&#x2F;pub&#x2F;mishegos-langsec-2021.pdf&quot;&gt;specific to the goals (Woodruff et al.)&lt;&#x2F;a&gt; of the target program.&lt;&#x2F;p&gt;
&lt;p&gt;The beauty of differential fuzzing is that you don&#x27;t need to create an abstract specification for correct behavior, at least not entirely from scratch.
That creation process can be difficult and error-prone (e.g. model checking, deductive verification).
Instead, our specification is provided by the programs under test.
Maybe that&#x27;s because one is a reference implementation written by an authority (e.g. manufacturer of device, inventor of a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;guidovranken.com&#x2F;2019&#x2F;05&#x2F;14&#x2F;differential-fuzzing-of-cryptographic-libraries&#x2F;&quot;&gt;cryptographic algorithm&lt;&#x2F;a&gt;).
Or maybe any divergence between untrusted implementations is an issue worth triaging.
Either way, differential fuzzing can test domain-specific properties far exceeding the complexity of what the borrow checker is capable of reasoning about.
So long as there&#x27;s a counterpart to diff against.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-the-goal-of-this-particular-differential-harness&quot;&gt;What&#x27;s the goal of this particular differential harness?&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s start by introducing the Program Under Test (PUT), &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;scapegoat&#x2F;latest&#x2F;scapegoat&#x2F;&quot;&gt;a data-structure library&lt;&#x2F;a&gt; I&#x27;ve been working on.
Though &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;scapegoat&#x2F;latest&#x2F;scapegoat&#x2F;&quot;&gt;&lt;code&gt;scapegoat&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is intended as a somewhat &quot;drop-in&quot; (largely API-compatible) replacement  for the standard library&#x27;s &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;collections&#x2F;struct.BTreeSet.html&quot;&gt;&lt;code&gt;BTreeSet&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&#x2F;&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;collections&#x2F;struct.BTreeMap.html&quot;&gt;&lt;code&gt;BTreeMap&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, it&#x27;s not as fast or mature - Rust&#x27;s standard ordered set&#x2F;map implementations are &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;cglab.ca&#x2F;~abeinges&#x2F;blah&#x2F;rust-btree-case&#x2F;&quot;&gt;masterpieces of systems programming&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;scapegoat&lt;&#x2F;code&gt; does, however, offer the following unique features:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;#![no_std]&lt;&#x2F;code&gt; portability&lt;&#x2F;strong&gt;: it&#x27;ll run on embedded devices without a dynamic memory allocator and&#x2F;or an OS (e.g. &quot;bare-metal&quot;).
Collection storage is stack-allocated using compile-time, per-constructor configuration (via const generics).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Strictly &lt;code&gt;#![forbid(unsafe_code)]&lt;&#x2F;code&gt;&lt;&#x2F;strong&gt;: the library, and all three of its dependencies, use &lt;em&gt;only&lt;&#x2F;em&gt; the safe subset of Rust. That means all emitted code maximizes memory safety guarantees for all possible executions.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Fallibility:&lt;&#x2F;strong&gt; &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lkml.org&#x2F;lkml&#x2F;2021&#x2F;4&#x2F;14&#x2F;1099&quot;&gt;Out-Of-Memory (OOM) &lt;code&gt;panic!&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is avoidable: &lt;code&gt;try_*&lt;&#x2F;code&gt; API variants return &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;scapegoat&#x2F;latest&#x2F;scapegoat&#x2F;enum.SgError.html&quot;&gt;&lt;code&gt;Result&amp;lt;_, SgError&amp;gt;&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;How can we be sure &lt;code&gt;scapegoat&lt;&#x2F;code&gt; correctly replicates the functionality of a standard library container under this set of self-imposed constraints?
Relying on unit tests alone is a bit egocentric.
If a developer had the omniscience to write unit tests for all possible edge cases, they&#x27;d likely also be capable of writing correct code on the first go.
This is where differential fuzzing comes in.&lt;&#x2F;p&gt;
&lt;p&gt;The remainder of this post is a hands-on tutorial in writing a differential harness for comparing &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;collections&#x2F;struct.BTreeMap.html&quot;&gt;&lt;code&gt;std::collections::BTreeMap&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; against &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;scapegoat&#x2F;latest&#x2F;scapegoat&#x2F;struct.SgMap.html&quot;&gt;&lt;code&gt;scapegoat::SgMap&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
Repetitive per-API code is excluded for brevity (for tis &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.nosweatshakespeare.com&#x2F;quotes&#x2F;famous&#x2F;brevity-is-the-soul-of-wit&#x2F;&quot;&gt;&quot;the soul of wit&quot;&lt;&#x2F;a&gt;!), but you can view the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tnballo&#x2F;scapegoat&#x2F;blob&#x2F;master&#x2F;fuzz&#x2F;fuzz_targets&#x2F;sg_map.rs&quot;&gt;real harness here&lt;&#x2F;a&gt;.
Our setup will be:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Coverage-guided:&lt;&#x2F;strong&gt; We&#x27;ll leverage granular instrumentation and genetic algorithms to automatically produce test cases that cover more of the code.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Structure-aware:&lt;&#x2F;strong&gt; The fuzzer&#x27;s input bit-stream will be transformed into a sequence of valid library API calls and parameters. That&#x27;s a best-case scenario for maximizing library coverage.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Differential:&lt;&#x2F;strong&gt; We&#x27;ll treat the &lt;code&gt;std::collections&lt;&#x2F;code&gt; APIs as &quot;known good&quot; models, and validate that &lt;code&gt;scapegoat&lt;&#x2F;code&gt;&#x27;s APIs are logically equivalent (return the same results) and equally reliable (don&#x27;t &lt;code&gt;panic!&lt;&#x2F;code&gt;).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Without further ado, let&#x27;s bash some bits!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rigging-up-the-harness&quot;&gt;Rigging Up the Harness&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;0-tooling-setup&quot;&gt;&lt;span class=&quot;title-sub&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;title-separator&quot;&gt;)&lt;&#x2F;span&gt; Tooling Setup&lt;&#x2F;h3&gt;
&lt;p&gt;We&#x27;ll use &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;llvm.org&#x2F;docs&#x2F;LibFuzzer.html&quot;&gt;&lt;code&gt;libFuzzer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;: a modern, mature, open-source fuzzer.
It&#x27;s actively maintained as part of the LLVM compiler infrastructure project - on which Rust and many others rely.
The &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-fuzz&#x2F;cargo-fuzz&quot;&gt;&lt;code&gt;cargo-fuzz&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; wrapper makes using &lt;code&gt;libFuzzer&lt;&#x2F;code&gt; easy and fun.
Assuming you already have the Rust &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;tools&#x2F;install&quot;&gt;toolchain installed&lt;&#x2F;a&gt; and are running x86-64 Linux or MacOS, getting set up takes just two commands:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#ffffff;&quot;&gt;&lt;code&gt;&lt;span&gt;rustup default nightly
&lt;&#x2F;span&gt;&lt;span&gt;cargo install cargo-fuzz
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While we need the nightly toolchain to perform fuzzing, it doesn&#x27;t introduce any dependencies to stable programs being fuzzed.
In other words, you can add harnesses to production libraries with low &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rust-lang.github.io&#x2F;rfcs&#x2F;2495-min-rust-version.html&quot;&gt;MSRVs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Next, clone the below repo and initialize a harness.
The repo contains &lt;code&gt;scapegoat&lt;&#x2F;code&gt; v2.1 code, but with a subtle bug intentionally inserted.
We&#x27;ll find this bug via fuzzing.&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#ffffff;&quot;&gt;&lt;code&gt;&lt;span&gt;git clone git@github.com:tnballo&#x2F;diff-fuzz-blog-post.git
&lt;&#x2F;span&gt;&lt;span&gt;cd diff-fuzz-blog-post
&lt;&#x2F;span&gt;&lt;span&gt;cargo fuzz init
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you&#x27;re on Windows, you can use the Docker container &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tnballo&#x2F;diff-fuzz-blog-post&#x2F;blob&#x2F;main&#x2F;Dockerfile&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;1-method-dispatch-and-argument-generation&quot;&gt;&lt;span class=&quot;title-sub&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;title-separator&quot;&gt;)&lt;&#x2F;span&gt; Method Dispatch and Argument Generation&lt;&#x2F;h3&gt;
&lt;p&gt;After running &lt;code&gt;cargo fuzz init&lt;&#x2F;code&gt;, you should have the following starter harness in &lt;code&gt;fuzz\fuzz_targets\fuzz_target_1.rs&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#ffffff;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;#![no_main]
&lt;&#x2F;span&gt;&lt;span&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;libfuzzer_sys::fuzz_target;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;fuzz_target!(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;data&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;]| {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; fuzzed code goes here
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The body of &lt;code&gt;fuzz_target&lt;&#x2F;code&gt; is &lt;code&gt;libFuzzer&lt;&#x2F;code&gt;&#x27;s entry point; it&#x27;ll get called repeatedly with random &lt;code&gt;data&lt;&#x2F;code&gt; until an error condition (crash, &lt;code&gt;panic!&lt;&#x2F;code&gt;, &lt;code&gt;assert!&lt;&#x2F;code&gt; failure, etc) is found.&lt;&#x2F;p&gt;
&lt;p&gt;To make our harness structure-aware, we need a way to convert the random, unstructured &lt;code&gt;data&lt;&#x2F;code&gt; stream into a sequence of calls to library APIs.
Per the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rust-fuzz.github.io&#x2F;book&#x2F;cargo-fuzz&#x2F;structure-aware-fuzzing.html&quot;&gt;Rust Fuzz Book&lt;&#x2F;a&gt;, the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;arbitrary&#x2F;1.0.3&#x2F;arbitrary&#x2F;trait.Arbitrary.html&quot;&gt;&lt;code&gt;Arbitrary&lt;&#x2F;code&gt; trait&lt;&#x2F;a&gt; lets us perform that conversion:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;We&#x27;ll create an &lt;code&gt;enum&lt;&#x2F;code&gt; in which each variant represents one library function and its parameters.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Because our  &lt;code&gt;enum&lt;&#x2F;code&gt; will derive &lt;code&gt;Arbitrary&lt;&#x2F;code&gt;, the fuzzer can choose function call order and generate parameters for each call.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Every generated parameter is of the correct &lt;em&gt;type&lt;&#x2F;em&gt; but has an unpredictable &lt;em&gt;value.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For this post, we&#x27;ll pick four map APIs to test: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;collections&#x2F;struct.BTreeMap.html#method.get&quot;&gt;&lt;code&gt;get&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;collections&#x2F;struct.BTreeMap.html#method.insert&quot;&gt;&lt;code&gt;insert&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;collections&#x2F;struct.BTreeMap.html#method.remove&quot;&gt;&lt;code&gt;remove&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, and &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;collections&#x2F;struct.BTreeMap.html#impl-Extend%3C(K%2C%20V)%3E&quot;&gt;&lt;code&gt;extend&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
That last interface is defined by a trait (&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Extend.html&quot;&gt;see &lt;code&gt;std::iter:Extend&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;), but that doesn&#x27;t make it special as far as writing the harness is concerned.
Fuzzing trait implementations is like fuzzing any other function.&lt;&#x2F;p&gt;
&lt;p&gt;To derive &lt;code&gt;Arbitrary&lt;&#x2F;code&gt;, we need to update &lt;code&gt;fuzz&#x2F;Cargo.toml&lt;&#x2F;code&gt; to include the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;arbitrary&quot;&gt;&lt;code&gt;arbitrary&lt;&#x2F;code&gt; crate&lt;&#x2F;a&gt; as a dependency:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#ffffff;&quot;&gt;&lt;code&gt;&lt;span&gt;[dependencies]
&lt;&#x2F;span&gt;&lt;span&gt;libfuzzer-sys = &amp;quot;0.4&amp;quot;
&lt;&#x2F;span&gt;&lt;span&gt;arbitrary = { version = &amp;quot;1&amp;quot;, features = [&amp;quot;derive&amp;quot;] }
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we can add our API-dispatch &lt;code&gt;enum&lt;&#x2F;code&gt; to &lt;code&gt;fuzz_target_1.rs&lt;&#x2F;code&gt;, along with imports for &lt;code&gt;Arbitrary&lt;&#x2F;code&gt;, &lt;code&gt;Debug&lt;&#x2F;code&gt;, and the data structures under test:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#ffffff;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;#![no_main]
&lt;&#x2F;span&gt;&lt;span&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;core::fmt::Debug;
&lt;&#x2F;span&gt;&lt;span&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;libfuzzer_sys::fuzz_target;
&lt;&#x2F;span&gt;&lt;span&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;arbitrary::Arbitrary;
&lt;&#x2F;span&gt;&lt;span&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;buggy_scapegoat::SgMap;
&lt;&#x2F;span&gt;&lt;span&gt;use &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;std::collections::BTreeMap;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;#[derive(Arbitrary, Debug)]
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;enum &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;MapMethod&amp;lt;K: Ord + Debug, V: Debug&amp;gt; {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    Get { key: K },
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    Insert { key: K, val: V },
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    Remove { key: K },
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Extend &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{ other: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;(K, V)&amp;gt; },
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;}
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;fuzz_target!(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;methods&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;MapMethod&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;&amp;gt;| {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; fuzzed code goes here
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note how we changed &lt;code&gt;fuzz_target&lt;&#x2F;code&gt;&#x27;s input type from &lt;code&gt;data: &amp;amp;[u8]&lt;&#x2F;code&gt; to &lt;code&gt;methods: Vec&amp;lt;MapMethod&amp;lt;usize, usize&amp;gt;&amp;gt;&lt;&#x2F;code&gt; (both types implement &lt;code&gt;Arbitrary&lt;&#x2F;code&gt;).
Instead of the fuzzer providing a buffer of data, it&#x27;ll provide a list of function&#x2F;parameter pairs.
Our choice of &lt;code&gt;usize&lt;&#x2F;code&gt; keys and values is better for throughput than using, say, &lt;code&gt;String&lt;&#x2F;code&gt;s or complex &lt;code&gt;struct&lt;&#x2F;code&gt;s.
But it doesn&#x27;t hamper our ability to test ordered map logic.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;2-logical-equivalence-assertions&quot;&gt;&lt;span class=&quot;title-sub&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;title-separator&quot;&gt;)&lt;&#x2F;span&gt; Logical Equivalence Assertions&lt;&#x2F;h3&gt;
&lt;p&gt;The final piece is the body of &lt;code&gt;fuzz_target&lt;&#x2F;code&gt;&#x27;s closure.
We need to create an instance of each data structure, iterate over &lt;code&gt;methods&lt;&#x2F;code&gt;, provide each input to both libraries, and check that the output and&#x2F;or effect is equivalent. Here is that differential logic:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#ffffff;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;fuzz_target!(|&lt;&#x2F;span&gt;&lt;span style=&quot;font-style:italic;color:#8aa6c1;&quot;&gt;methods&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;lt;MapMethod&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;&amp;gt;&amp;gt;| {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;const &lt;&#x2F;span&gt;&lt;span style=&quot;color:#66ccff;&quot;&gt;CAPACITY&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;: &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;usize &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#eddd5a;&quot;&gt;2048&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; sg_map &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;SgMap::&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, &lt;&#x2F;span&gt;&lt;span&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;, CAPACITY&amp;gt;::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Data structure under test
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let mut&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; bt_map &lt;&#x2F;span&gt;&lt;span&gt;= &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;BTreeMap::new(); &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Reference data structure
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; m &lt;&#x2F;span&gt;&lt;span&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; methods {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; m {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            MapMethod::Get { key } &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                assert_eq!(
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    sg_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;key),
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    bt_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;key)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                );
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            MapMethod::Insert { key, val } &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; sg_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; sg_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    assert_eq!(
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                        sg_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(key, val),
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                        bt_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(key, val)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    );
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    assert_eq!(sg_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(), bt_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;());
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            MapMethod::Remove { key } &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                assert_eq!(
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    sg_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;remove&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;key),
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    bt_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;remove&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;key)
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                );
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                assert_eq!(sg_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(), bt_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;());
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            MapMethod::Extend { other } &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;if &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(sg_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() &lt;&#x2F;span&gt;&lt;span&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; other.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()) &lt;&#x2F;span&gt;&lt;span&gt;&amp;lt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; sg_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    sg_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;extend&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(other.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;());
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    bt_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;extend&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(other.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;());
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                    assert!(sg_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;().&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;eq&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(bt_map.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;()));
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;                }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    }
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;});
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;MapMethod::Get&lt;&#x2F;code&gt; and &lt;code&gt;MapMethod::Remove&lt;&#x2F;code&gt; are straightforward: both map implementations should return the same value, if any, because they maintain the same key-value pairs. To verify that both collections report the same length after item removal, we add the post-condition &lt;code&gt;assert_eq!(sg_map.len(), bt_map.len());&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;MapMethod::Insert&lt;&#x2F;code&gt; and &lt;code&gt;MapMethod::Extend&lt;&#x2F;code&gt; are a tad more nuanced.
Both check that &lt;code&gt;sg_map&lt;&#x2F;code&gt;&#x27;s fixed stack capacity won&#x27;t be exceeded prior to adding items.
We could have used &lt;code&gt;SgMap&lt;&#x2F;code&gt;&#x27;s fallible &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;scapegoat&#x2F;latest&#x2F;scapegoat&#x2F;struct.SgMap.html#method.try_insert&quot;&gt;&lt;code&gt;try_insert&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;scapegoat&#x2F;latest&#x2F;scapegoat&#x2F;struct.SgMap.html#method.try_extend&quot;&gt;&lt;code&gt;try_extend&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to handle potential errors instead of avoiding them, but the above approach offers a more direct comparison against &lt;code&gt;BTreeMap&lt;&#x2F;code&gt;&#x27;s APIs.
And it demonstrates a technique for encoding capacity, a factor otherwise unknown to the fuzzer, within the harness.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Map::Extend&lt;&#x2F;code&gt;&#x27;s final line, &lt;code&gt;assert!(sg_map.iter().eq(bt_map.iter()));&lt;&#x2F;code&gt;, solves a subtle problem.
After extending both collections, we&#x27;d like to ensure they contain the same items.
But &lt;code&gt;SgMap&lt;&#x2F;code&gt; and &lt;code&gt;BTreeMap&lt;&#x2F;code&gt; are different types, so we can&#x27;t rely on the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;cmp&#x2F;trait.Eq.html&quot;&gt;&lt;code&gt;Eq&lt;&#x2F;code&gt; trait&lt;&#x2F;a&gt;.
Instead, we compare their ordered iterators - which produce items of comparable type.&lt;&#x2F;p&gt;
&lt;p&gt;These &lt;code&gt;assert&lt;&#x2F;code&gt;s of equivalence give &lt;code&gt;libFuzzer&lt;&#x2F;code&gt; a semantically rich &lt;em&gt;bug oracle&lt;&#x2F;em&gt;.
Instead of relying on crashes, the fuzzer uses a hybrid of &quot;state-machine&quot; and &quot;specification&quot; (a formidable chimera!) to validate a complex notion of &quot;correctness&quot;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;finding-the-bug&quot;&gt;Finding the Bug&lt;&#x2F;h2&gt;
&lt;p&gt;Recall that the repo for this post purposely introduces an insidious bug.
It&#x27;s a &lt;em&gt;logic bug&lt;&#x2F;em&gt; within a function for removing nodes from a binary tree.
The full context of how this function works isn&#x27;t important (see &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tnballo&#x2F;diff-fuzz-blog-post&#x2F;blob&#x2F;main&#x2F;src&#x2F;tree&#x2F;tree.rs#L790&quot;&gt;source&lt;&#x2F;a&gt; if interested).&lt;&#x2F;p&gt;
&lt;p&gt;The important part is that the bug can cause our library to silently &quot;lose&quot; a subtree.
From an end-user&#x27;s perspective, this means items they insert can magically disappear.
But only some of the items, and only some of the time.
That&#x27;s bananas!&lt;&#x2F;p&gt;
&lt;p&gt;The original, bug-free code snippet looked like this:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#ffffff;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; min_node &lt;&#x2F;span&gt;&lt;span&gt;= &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.arena[min_idx];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; min_node.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;left_idx&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Continue search for min node
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(lt_idx) &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            min_parent_idx &lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; min_idx;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            min_idx &lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; lt_idx;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; More code here...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here&#x27;s the buggy code:&lt;&#x2F;p&gt;
&lt;pre data-lang=&quot;rust&quot; style=&quot;background-color:#191919;color:#ffffff;&quot; class=&quot;language-rust &quot;&gt;&lt;code class=&quot;language-rust&quot; data-lang=&quot;rust&quot;&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;loop &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; min_node &lt;&#x2F;span&gt;&lt;span&gt;= &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;self.arena[min_idx];
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;    &lt;&#x2F;span&gt;&lt;span style=&quot;color:#80d500;&quot;&gt;match&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; min_node.&lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;left_idx&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;() {
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; Continue search for min node
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        &lt;&#x2F;span&gt;&lt;span style=&quot;color:#8aa6c1;&quot;&gt;Some&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;(lt_idx) &lt;&#x2F;span&gt;&lt;span&gt;=&amp;gt; &lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;{
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            min_idx &lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; lt_idx;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;            min_parent_idx &lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt; min_idx;
&lt;&#x2F;span&gt;&lt;span style=&quot;color:#cccccc;&quot;&gt;        }
&lt;&#x2F;span&gt;&lt;span style=&quot;background-color:#171717;color:#616161;&quot;&gt;&#x2F;&#x2F; More code here...
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The bug swaps the order of the two statements nested within the &lt;code&gt;Some&lt;&#x2F;code&gt; match arm.
That would be tricky to spot in code review, even for the eagle-eyed.
I would know: this is a real bug I inadvertently introduced early in &lt;code&gt;scapegoat&lt;&#x2F;code&gt;&#x27;s development.&lt;&#x2F;p&gt;
&lt;p&gt;Worse yet, the buggy library passes all &lt;code&gt;rustdoc&lt;&#x2F;code&gt; tests.
These tests are &lt;del&gt;stolen&lt;&#x2F;del&gt; ported directly from &lt;code&gt;BTreeMap&lt;&#x2F;code&gt;&#x27;s API documentation, meaning &lt;em&gt;all&lt;&#x2F;em&gt; map example code works perfectly fine.
The bug isn&#x27;t triggered unless the internal tree is in a particular state when a particular node is removed.
Because the tree is self-balancing, that state isn&#x27;t trivial to reproduce.
Well, unless you&#x27;re using a differential fuzzer.
Which can find the bad state in &lt;em&gt;mere seconds&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We could start the fuzzing campaign with the simple command &lt;code&gt;cargo fuzz run fuzz_target_1&lt;&#x2F;code&gt;, but for real-world use it&#x27;s often worth augmenting the command with some of the below flags:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#ffffff;&quot;&gt;&lt;code&gt;&lt;span&gt;cargo fuzz run fuzz_target_1 --release --debug-assertions -s address --jobs $(nproc) -- -max_len=65536
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--release&lt;&#x2F;code&gt; ensures the binary is compiled with optimizations, aiding throughput.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--debug-assertions&lt;&#x2F;code&gt; enables &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;macro.debug_assert.html&quot;&gt;&lt;code&gt;debug_assert!&lt;&#x2F;code&gt; statements&lt;&#x2F;a&gt; and integer overflow checks (despite &lt;code&gt;release&lt;&#x2F;code&gt; mode). This flag can help catch interesting invariant violations a fuzzer would otherwise miss.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-s address&lt;&#x2F;code&gt; enables &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;clang.llvm.org&#x2F;docs&#x2F;AddressSanitizer.html&quot;&gt;&lt;code&gt;AddressSanitizer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, a granular instrumentation tool that can catch memory corruption errors as tiny as a single byte in size - even if the program doesn&#x27;t crash or change it&#x27;s output. While this needlessly lowers throughput when fuzzing a fully safe Rust program, it&#x27;s a good habit to get into if you rely on &lt;code&gt;unsafe&lt;&#x2F;code&gt; dependencies.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--jobs $(nproc)&lt;&#x2F;code&gt; is a Linux-ism for starting one fuzzer instance&#x2F;job per available host core. On a multi-core machine, this makes fuzzing far more efficient. &lt;code&gt;libFuzzer&lt;&#x2F;code&gt;&#x27;s internals allow jobs to coordinate seeds&#x2F;mutations among themselves.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;-max_len=65536&lt;&#x2F;code&gt; increases the upper limit length of the byte-stream produced by the fuzzer (what we&#x27;re converting to API calls). The default would&#x27;ve still caught our crash in this example, but testing longer call sequences is generally a good idea.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Note &lt;code&gt;--release&lt;&#x2F;code&gt;, &lt;code&gt;--debug-assertions&lt;&#x2F;code&gt;, and &lt;code&gt;-s address&lt;&#x2F;code&gt; are default settings: they apply even if these flags are omitted.
But being explicit never hurts, and the flags&#x27; functionality is worth understanding.&lt;&#x2F;p&gt;
&lt;p&gt;After running the above command to kick-off a fuzzing campaign, you&#x27;ll see terminal scroll with mutation and&#x2F;or coverage information.
But soon the fuzzer will find an &lt;code&gt;assert&lt;&#x2F;code&gt; failure!
It may take a couple seconds, depending on the speed of your machine.
Once the failure is found, you should see a message akin to the following buried before a stack trace:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#ffffff;&quot;&gt;&lt;code&gt;&lt;span&gt;thread &amp;#39;&amp;lt;unnamed&amp;gt;&amp;#39; panicked at &amp;#39;assertion failed: sg_map.iter().eq(bt_map.iter())&amp;#39;, fuzz_targets&#x2F;fuzz_target_1.rs:49:21
&lt;&#x2F;span&gt;&lt;span&gt;note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
&lt;&#x2F;span&gt;&lt;span&gt;==33023== ERROR: libFuzzer: deadly signal
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Toward the bottom of the output, you&#x27;ll see a command provided underneath the text &lt;code&gt;Minimize test case with:&lt;&#x2F;code&gt;.
&lt;code&gt;LibFuzzer&lt;&#x2F;code&gt; has a built-in minimizer that will take a crashing input and attempt to shrink it down to the smallest possible input that still causes the same crash. Copy&#x2F;paste and run this command, which should look like the below:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#ffffff;&quot;&gt;&lt;code&gt;&lt;span&gt;cargo fuzz tmin -O -a fuzz_target_1 fuzz&#x2F;artifacts&#x2F;fuzz_target_1&#x2F;crash-&amp;lt;SOME_HASH&amp;gt;
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the crash discovered on my machine, the minimization result was:&lt;&#x2F;p&gt;
&lt;pre style=&quot;background-color:#191919;color:#ffffff;&quot;&gt;&lt;code&gt;&lt;span&gt;Minimized artifact:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	fuzz&#x2F;artifacts&#x2F;fuzz_target_1&#x2F;minimized-from-f4b1b840a1627a2a3b427fd923adec6aaf5c958b
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;Output of `std::fmt::Debug`:
&lt;&#x2F;span&gt;&lt;span&gt;
&lt;&#x2F;span&gt;&lt;span&gt;	[
&lt;&#x2F;span&gt;&lt;span&gt;	    Extend {
&lt;&#x2F;span&gt;&lt;span&gt;	        other: [
&lt;&#x2F;span&gt;&lt;span&gt;	            (
&lt;&#x2F;span&gt;&lt;span&gt;	                12225489209634957737,
&lt;&#x2F;span&gt;&lt;span&gt;	                18446744073695242665,
&lt;&#x2F;span&gt;&lt;span&gt;	            ),
&lt;&#x2F;span&gt;&lt;span&gt;	            (
&lt;&#x2F;span&gt;&lt;span&gt;	                18446744073709551615,
&lt;&#x2F;span&gt;&lt;span&gt;	                18446744073709551615,
&lt;&#x2F;span&gt;&lt;span&gt;	            ),
&lt;&#x2F;span&gt;&lt;span&gt;	            (
&lt;&#x2F;span&gt;&lt;span&gt;	                18446744073709551103,
&lt;&#x2F;span&gt;&lt;span&gt;	                8029759142086311935,
&lt;&#x2F;span&gt;&lt;span&gt;	            ),
&lt;&#x2F;span&gt;&lt;span&gt;	            (
&lt;&#x2F;span&gt;&lt;span&gt;	                2965947086368182160,
&lt;&#x2F;span&gt;&lt;span&gt;	                8214752266484842281,
&lt;&#x2F;span&gt;&lt;span&gt;	            ),
&lt;&#x2F;span&gt;&lt;span&gt;	        ],
&lt;&#x2F;span&gt;&lt;span&gt;	    },
&lt;&#x2F;span&gt;&lt;span&gt;	    Remove {
&lt;&#x2F;span&gt;&lt;span&gt;	        key: 12225489209634957737,
&lt;&#x2F;span&gt;&lt;span&gt;	    },
&lt;&#x2F;span&gt;&lt;span&gt;	    Extend {
&lt;&#x2F;span&gt;&lt;span&gt;	        other: [],
&lt;&#x2F;span&gt;&lt;span&gt;	    },
&lt;&#x2F;span&gt;&lt;span&gt;	]
&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now if we didn&#x27;t already know where the bug is, we could manually translate this minimized call sequence into a short unit test ending with the fuzzer output&#x27;s failing assert (&lt;code&gt;assert!(sg_map.iter().eq(bt_map.iter()));&lt;&#x2F;code&gt;).
From there it&#x27;s a matter of using &lt;code&gt;gdb&lt;&#x2F;code&gt; (or &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rr-project.org&#x2F;&quot;&gt;Mozilla &lt;code&gt;rr&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;) to root cause the test failure.
And we get to keep that unit test in our suite afterwards.&lt;&#x2F;p&gt;
&lt;p&gt;Notice how the &lt;code&gt;assert&lt;&#x2F;code&gt; fires after the fuzzer calls &lt;code&gt;extend&lt;&#x2F;code&gt; with an empty list (last call in the sequence) and compares iterators, even though it was the previous &lt;code&gt;remove&lt;&#x2F;code&gt; call that caused our library to enter a &quot;bad state&quot;.
It&#x27;s shockingly common for the root cause of an error to be far, in terms of SLoC or execution time, from where the error is detected.
Thankfully, the minimized test case provides a full sequence of reproducible events.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;takeaway&quot;&gt;&lt;span class=&quot;title-sub&quot;&gt;Takeaway&lt;&#x2F;span&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A pessimist would grumble at the notion of relying on random chance to secure code.
An optimist will highlight that stochastic processes are widely used in mathematical modeling to draw empirical conclusions.
A realist knows the weakest link is the first to be compromised, and even the dumbest of fuzzers can find shallow bugs before an adversary does.&lt;&#x2F;p&gt;
&lt;p&gt;Since the heyday of AFL, coverage-guided fuzzing has been the darling of dynamic security analysis.
Many an academic hath dubiously claimed to build atop the shoulders of the giant.
But, to again quote Shakespare completely out of context, &quot;no legacy is so rich as honesty&quot;.
And the current data indicates the coverage-guided king has yet to be convincingly dethroned.&lt;&#x2F;p&gt;
&lt;p&gt;Rust code may seldom fall victim to the bug classes for which &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;clang.llvm.org&#x2F;docs&#x2F;AddressSanitizer.html&quot;&gt;&lt;code&gt;AddressSanitizer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;clang.llvm.org&#x2F;docs&#x2F;MemorySanitizer.html&quot;&gt;&lt;code&gt;MemorySanitizer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; are so keenly attuned.
Yet fuzzing&#x27;s reign is far from over.
A well-designed harness can hunt down trigger-able memory corruption vulnerabilities in &lt;code&gt;unsafe&lt;&#x2F;code&gt; dependencies, or, in the differential case, even semantically-meaningful logic bugs.&lt;&#x2F;p&gt;
&lt;p&gt;Run that differential fuzzer long enough and the line between fuzzing and &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Model_checking&quot;&gt;model checking&lt;&#x2F;a&gt; starts to blur.
You might be tempted to claim you&#x27;ve demonstrated the equivalence of &lt;em&gt;logical state-spaces&lt;&#x2F;em&gt; between two non-trivial programs.
Informally, that could mean:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;An &lt;strong&gt;interface-level&lt;&#x2F;strong&gt;, &lt;strong&gt;stochastic&lt;&#x2F;strong&gt; guarantee that the &lt;strong&gt;internal actions&lt;&#x2F;strong&gt; of two &lt;strong&gt;transition systems&lt;&#x2F;strong&gt; are semantically equivalent. Where:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;interface&lt;&#x2F;strong&gt; is defined by the APIs under test, consuming potentially attacker-controlled inputs.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Stochastic&lt;&#x2F;strong&gt; implies not absolute (constrained by limitations of dynamic testing) but powerful nonetheless.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Internal actions&lt;&#x2F;strong&gt; are &quot;hidden&quot; logic (e.g. inner-workings of disparate data structures backing the same API).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Transition systems&lt;&#x2F;strong&gt; are state machines represented by the real PUTs, not specifications or models.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So why aren&#x27;t we all fuzzing security-sensitive surfaces, at least for a modest number of cycles?
Well that comes down to the difference between apes and programmers: apes &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;TtPXYPJ5_eE?t=423&quot;&gt;know when&lt;&#x2F;a&gt; they should be using tools.&lt;&#x2F;p&gt;
&lt;p&gt;Fortunately for us, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;llvm.org&#x2F;docs&#x2F;LibFuzzer.html&quot;&gt;&lt;code&gt;libFuzzer&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; (C&#x2F;C++ backend&#x2F;frontend) and &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rust-fuzz.github.io&#x2F;book&#x2F;cargo-fuzz.html&quot;&gt;&lt;code&gt;cargo-fuzz&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; (Rust frontend) make it delightfully easy to get those typewriters tapping.
Maybe to justify confidence in our own security posture.
Or, perhaps, to manifest a CVE masterpiece from the coverage-spelunking depths of someone else&#x27;s code.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;I&#x27;d like to thank GitHub user &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TheDoctor314&quot;&gt;TheDoctor314&lt;&#x2F;a&gt; for their contributions to the &lt;code&gt;scapegoat&lt;&#x2F;code&gt; crate, including stable-toolchain implementations of counterparts to nightly-only &lt;code&gt;BTreeMap&lt;&#x2F;code&gt; APIs. Much appreciated!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Read a free technical book!&lt;&#x2F;strong&gt;
I&#x27;m fulfilling a lifelong dream and writing a book.
It&#x27;s about developing secure and robust systems software.
Although a work-in-progress, the book is freely available online (no paywalls or obligations):
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;highassurance.rs&#x2F;&quot;&gt;https:&#x2F;&#x2F;highassurance.rs&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Blue Team Rust: What is &quot;Memory Safety&quot;, Really?</title>
        <published>2020-07-29T00:00:00+00:00</published>
        <updated>2020-07-29T00:00:00+00:00</updated>
        <rights type="html">&amp;copy; 2020-2025 Tiemoko Ballo</rights>
        
        <author>
          <name>
            
              Tiemoko Ballo
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://tiemoko.com/blog/blue-team-rust/"/>
        <id>https://tiemoko.com/blog/blue-team-rust/</id>
        
        <content type="html" xml:base="https://tiemoko.com/blog/blue-team-rust/">&lt;hr &#x2F;&gt;
&lt;p&gt;&lt;em&gt;08-02-2020 update: &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;i268wh&#x2F;blue_team_rust_what_is_memory_safety_really&#x2F;&quot;&gt;Reddit discussion here&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=24024876&quot;&gt;Hacker News here&lt;&#x2F;a&gt;. Appreciate all the community feedback!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p align=&quot;center&quot;&gt;
  &lt;img src=&quot;..&amp;#x2F;..&amp;#x2F;images&amp;#x2F;btr_mem.svg&quot; alt=&quot;Rust Memory Safety&quot; style=&quot;width:100%&quot;&gt;
&lt;&#x2F;p&gt;
&lt;p&gt;Tools shape both their user and their result.
Paradigms of C and C++ have molded generations of systems programmers, the ubiquity and staying power of both languages is a testament to their utility.
But the resultant software has suffered decades of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;msrc-blog.microsoft.com&#x2F;2019&#x2F;07&#x2F;16&#x2F;a-proactive-approach-to-more-secure-code&#x2F;&quot;&gt;memory corruption CVEs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Rust, as a compiled language &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;blog.discordapp.com&#x2F;why-discord-is-switching-from-go-to-rust-a190bbca2b1f&quot;&gt;without garbage collection&lt;&#x2F;a&gt;, supports what have traditionally been C&#x2F;C++ domains.
This includes everything from high-performance distributed systems to microcontroller firmware.
Rust offers an alternative set of paradigms, namely &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;depth-first.com&#x2F;articles&#x2F;2020&#x2F;01&#x2F;27&#x2F;rust-ownership-by-example&#x2F;&quot;&gt;ownership and lifetimes&lt;&#x2F;a&gt;.
If you&#x27;ve never tried Rust, imagine pair programming alongside a nearly-omniscient but narrowly-focused perfectionist.
That&#x27;s what the borrow checker, a compiler component implementing the ownership concept, can sometimes feel like.
In exchange for the associated learning curve, we get memory safety guarantees.&lt;&#x2F;p&gt;
&lt;p&gt;Like many in the security community, I&#x27;ve been drawn to Rust by the glittering promise of a safe alternative.
But what does &quot;safe&quot; actually mean on a technical level?
Is the draw one of moths to flame, or does Rust fundamentally change the game?&lt;&#x2F;p&gt;
&lt;p&gt;This post is my attempt to answer these questions, based on what I&#x27;ve learned so far.
Memory safety is a topic knee-deep in operating system and computer architecture concepts, so I have to assume formidable prior systems security knowledge to keep this post short-ish.
Whether you&#x27;re already using Rust or are just flirting with the idea, hope you find it useful!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-exactly-are-the-memory-safety-guarantees-in-terms-of-exploitability&quot;&gt;What exactly are the &quot;memory safety guarantees&quot;? In terms of exploitability?&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s start with the good news. Rust largely prevents a major vector for information leakage and malicious code execution:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Stack protection:&lt;&#x2F;strong&gt; Classic stack-smashing is now an &lt;em&gt;exception&lt;&#x2F;em&gt; and not &lt;em&gt;memory corruption&lt;&#x2F;em&gt;; attempts to write past the end of a buffer will trigger a panic instead of leading to &lt;em&gt;buffer overflow&lt;&#x2F;em&gt;. Regardless of panic handling logic (e.g. &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;panic-reset&quot;&gt;&lt;code&gt;panic_reset&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;), your application could still be subject to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;cwe.mitre.org&#x2F;data&#x2F;definitions&#x2F;730.html&quot;&gt;Denial of Service (DoS)&lt;&#x2F;a&gt; attacks. This is why fuzzing Rust is &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;blog.hackeriet.no&#x2F;fuzzing-sequoia&#x2F;&quot;&gt;still worthwhile&lt;&#x2F;a&gt;. But, as the panic prevents attacker-controlled stack corruption, you won&#x27;t fall victim to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Arbitrary_code_execution&quot;&gt;Arbitrary or Remote Code Execution (ACE and RCE, respectively)&lt;&#x2F;a&gt;. Attempts to read past the end of a buffer are similarly stopped, so &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;blog.getreu.net&#x2F;projects&#x2F;embedded-system-security-with-Rust&#x2F;&quot;&gt;no Heartbleed-style bugs&lt;&#x2F;a&gt;. Enforcement is dynamic: the compiler inserts runtime bounds checks where necessary, incurring small performance overhead. Bounds checks are more effective than the stack cookies a C compiler might insert because they still apply when indexing linear data structures, an operation that&#x27;s easier to get right with Rust&#x27;s &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;index.html&quot;&gt;iterator APIs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Heap protection:&lt;&#x2F;strong&gt; Bounds checks and panic behavior still apply to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;heap-exploitation.dhavalkapil.com&#x2F;&quot;&gt;heap-allocated&lt;&#x2F;a&gt; objects. In addition, the ownership paradigm eliminates dangling pointers, preventing &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;cwe.mitre.org&#x2F;data&#x2F;definitions&#x2F;416.html&quot;&gt;Use-After-Free (UAF)&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;cwe.mitre.org&#x2F;data&#x2F;definitions&#x2F;415.html&quot;&gt;Double-Free (DF)&lt;&#x2F;a&gt; vulnerabilities: heap metadata is never corrupted. Memory leaks (meaning never freeing allocations, not over-reading data) are still possible if a programmer creates &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;book&#x2F;ch15-06-reference-cycles.html&quot;&gt;cyclical references&lt;&#x2F;a&gt;. Compile-time static analysis does the enforcement, soundly reasoning about abstract states representing all possible dynamic executions. There is no runtime cost. Effectiveness is maximal: the program simply can&#x27;t enter a bad state.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;References are always valid and variables are initialized before use:&lt;&#x2F;strong&gt; safe Rust doesn&#x27;t allow manipulation of raw pointers, ensuring that pointer dereferences are valid. This means no &lt;code&gt;NULL&lt;&#x2F;code&gt; dereferences for DoS and no pointer manipulation for control flow hijack or arbitrary read&#x2F;write. The &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;option&#x2F;enum.Option.html&quot;&gt;&lt;code&gt;Option&lt;&#x2F;code&gt; type&lt;&#x2F;a&gt; facilitates error handling when &lt;code&gt;NULL&lt;&#x2F;code&gt; is a concept the programmer wishes to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;nomicon&#x2F;ffi.html#the-nullable-pointer-optimization&quot;&gt;logically express&lt;&#x2F;a&gt;. These are compile-time guarantees, courtesy of ownership and lifetimes. A similar compile-time guarantee ensures variables can&#x27;t be read until they&#x27;ve been initialized. Use of uninitialized variables is a warning in most modern C compilers; that aspect isn&#x27;t novel. But ensuring valid dereferences certainly is.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Data races are completely eliminated:&lt;&#x2F;strong&gt; Rust&#x27;s ownership system ensures that any given variable can only have one writer (e.g. a mutable reference) at any given program point, but an unlimited number of readers (e.g. immutable references). In addition to enabling memory safety, this scheme solves the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Readers%E2%80%93writers_problem&quot;&gt;classic readers-writers concurrency problem&lt;&#x2F;a&gt;. Thus Rust eliminates data races, sometimes without the need for synchronization primitives or reference counting - but not &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;ADbCqH7_SAs?t=669&quot;&gt;race conditions in general&lt;&#x2F;a&gt;. Data race prevention reduces opportunities for &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.redballoonsecurity.com&#x2F;publications&#x2F;papers&#x2F;Concurrency_Attacks.pdf&quot;&gt;concurrency attacks&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;All good things in life come with a caveat. Let&#x27;s look at the fine print:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Not all Rust code is memory safe:&lt;&#x2F;strong&gt; Satisfying the compiler&#x27;s analyses is part of what makes implementing certain data structures, like &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rust-unofficial.github.io&#x2F;too-many-lists&#x2F;fourth.html&quot;&gt;doubly-linked lists&lt;&#x2F;a&gt;, challenging in Rust. Moreover, certain low-level operations, like &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Memory-mapped_I&#x2F;O&quot;&gt;Memory Mapped I&#x2F;O (MMIO)&lt;&#x2F;a&gt;, are difficult to &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-embedded&#x2F;register-rs&quot;&gt;fully analyze&lt;&#x2F;a&gt; for safety. Blocks of code marked as &lt;code&gt;unsafe&lt;&#x2F;code&gt; are manually-designated &quot;blindspots&quot; for the analyses, relaxing safety-specific checks since the programmer vouches for their correctness. This includes parts of Rust&#x27;s standard library, for which &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gts3.org&#x2F;2019&#x2F;cve-2018-1000657.html&quot;&gt;CVE numbers have been assigned&lt;&#x2F;a&gt;, and, by extension, any external libraries called via C &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Foreign_function_interface&quot;&gt;Foreign Function Interface&lt;&#x2F;a&gt; (CFFI). Furthermore, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;2003.03296&quot;&gt;researchers have found&lt;&#x2F;a&gt; that ownership&#x27;s automatic destruction can create new (meaning unique to Rust) UAF and DF patterns in &lt;code&gt;unsafe&lt;&#x2F;code&gt; code. &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;system&#x2F;files&#x2F;conference&#x2F;usenixsecurity18&#x2F;sec18-silvestro.pdf&quot;&gt;Hardened allocators&lt;&#x2F;a&gt;, which check heap consistency invariants dynamically, aren&#x27;t entirely obsolete. Memory safety guarantees apply &lt;em&gt;broadly&lt;&#x2F;em&gt;, not &lt;em&gt;universally&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;unsafe&lt;&#x2F;code&gt; drops memory safety guarantees for a limited scope and doesn&#x27;t eliminate all checks:&lt;&#x2F;strong&gt; &lt;code&gt;unsafe&lt;&#x2F;code&gt; isn&#x27;t a free-for-all. Type, lifetime, and reference checks are still active; high-risk operations have explicit APIs (e.g. &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.slice.html#method.get_unchecked&quot;&gt;&lt;code&gt;get_unchecked&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;). The CFFI boundary may be a &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rustsec.org&#x2F;advisories&#x2F;RUSTSEC-2019-0005.html&quot;&gt;weak link&lt;&#x2F;a&gt;. While memory corruption is possible with &lt;code&gt;unsafe&lt;&#x2F;code&gt;, the possibility is constrained to small portions of your codebase - around 1% of a typical Rust library &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;NQBVUjdkLAA?t=1413&quot;&gt;by one estimate&lt;&#x2F;a&gt;. From a security audit perspective, that&#x27;s a colossal reduction in attack surface for a major bug class. Think of &lt;code&gt;unsafe&lt;&#x2F;code&gt; as a small &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Trusted_computing_base&quot;&gt;Trusted Computing Base (TCB)&lt;&#x2F;a&gt; in a larger system.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Interior mutability can push borrow checks to runtime:&lt;&#x2F;strong&gt; the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;book&#x2F;ch15-05-interior-mutability.html&quot;&gt;interior mutability pattern&lt;&#x2F;a&gt; allows multiple mutable aliases to a single memory location so long as they&#x27;re not in use simultaneously. It&#x27;s a sidestep of the borrow checker, a fallback when the problem can&#x27;t be &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;indextree&quot;&gt;reframed in an idiomatic way&lt;&#x2F;a&gt; for powerful compile-time guarantees. Safe &lt;em&gt;wrappers&lt;&#x2F;em&gt; for &lt;code&gt;unsafe&lt;&#x2F;code&gt; APIs (e.g. &lt;code&gt;Rc&amp;lt;RefCell&amp;lt;T&amp;gt;&amp;gt;&lt;&#x2F;code&gt;, &lt;code&gt;Arc&amp;lt;Mutex&amp;lt;T&amp;gt;&amp;gt;&lt;&#x2F;code&gt;) verify exclusivity at runtime, incurring a performance penalty and introducing the potential to panic. I couldn&#x27;t find metrics on how widely used this pattern is or isn&#x27;t, but would again recommend &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rust-fuzz.github.io&#x2F;book&#x2F;afl&#x2F;tutorial.html&quot;&gt;fuzzing&lt;&#x2F;a&gt; for probabilistic panic detection.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;To be honest, decades of hardware, OS, and compiler-level defenses have hardened C and C++ deployments.
Memory corruption 0-days aren&#x27;t exactly low-hanging fruit.
Yet Rust still feels like a significant step forward and a noteworthy improvement to the security posture of performance-critical software.
Even though the &lt;code&gt;unsafe&lt;&#x2F;code&gt; escape hatch must exist, memory corruption - a large and vicious bug class - is largely eliminated.&lt;&#x2F;p&gt;
&lt;p&gt;So is Rust the new messiah, sent to save us from the hell of remote shell?
Definitely not.
Rust won&#x27;t stop command injection (e.g. part of an input string ending up as an argument to &lt;code&gt;execve&lt;&#x2F;code&gt;).
Or misconfiguration (e.g. fallback to an insecure cipher).
Or logic bugs (e.g. forgetting to verify user permissions).
No general purpose programming language will make your code inherently secure or formally correct.
But at least you don&#x27;t have to worry about these kinds of mistakes &lt;em&gt;and&lt;&#x2F;em&gt; maintaining &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;alexgaynor.net&#x2F;2019&#x2F;apr&#x2F;21&#x2F;modern-c++-wont-save-us&#x2F;&quot;&gt;complex, invisible memory invariants&lt;&#x2F;a&gt; throughout your Rust codebase.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ok-what-about-embedded-systems-aren-t-those-super-vulnerable&quot;&gt;OK, what about embedded systems? Aren&#x27;t those super vulnerable?&lt;&#x2F;h2&gt;
&lt;p&gt;Let&#x27;s assume &quot;embedded&quot; means no OS abstractions; the software stack is a single, monolithic binary (e.g. AVR or Cortex-M firmware) or part of the OS itself (e.g. kernel or bootloader). Rust&#x27;s &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;cliffle.com&#x2F;blog&#x2F;m4vga-in-rust&#x2F;#on-no-std&quot;&gt;&lt;code&gt;#![no_std]&lt;&#x2F;code&gt; attribute&lt;&#x2F;a&gt; facilitates developing for embedded platforms.
&lt;code&gt;#![no_std]&lt;&#x2F;code&gt; Rust libraries typically forsake dynamic collections (like &lt;code&gt;Vec&lt;&#x2F;code&gt; and &lt;code&gt;HashMap&lt;&#x2F;code&gt;) for portability to baremetal environments (no memory allocator, no heap).
The borrow checker barrier is minimal without dynamic memory, so prototyping ease remains roughly equivalent to embedded C - albeit with &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;forge.rust-lang.org&#x2F;release&#x2F;platform-support.html&quot;&gt;fewer&lt;&#x2F;a&gt; supported &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gcc.gnu.org&#x2F;install&#x2F;specific.html&quot;&gt;architectures&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The resource-constrained and&#x2F;or real-time embedded systems &lt;code&gt;#![no_std]&lt;&#x2F;code&gt; targets often lack modern mitigations like &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Dvug1Hup2iA&quot;&gt;a Memory Protection Unit (MPU), No eXecute (NX), or Address Space Layout Randomization (ASLR)&lt;&#x2F;a&gt;.
We&#x27;re talking about a lawless land where memory is flat and no one can hear you segfault.
But Rust still gives us that sweet, sweet bound check insurance when running baremetal without an allocator.
That&#x27;s noteworthy because it might be the &lt;em&gt;first&lt;&#x2F;em&gt; and &lt;em&gt;last&lt;&#x2F;em&gt; line of defense in an embedded scenario.
Just remember that low-level interaction with hardware will probably require some amount of &lt;code&gt;unsafe&lt;&#x2F;code&gt; code, in which memory access without bounds check is opt-in.&lt;&#x2F;p&gt;
&lt;p&gt;For x86&#x2F;x64, &lt;em&gt;stack probes&lt;&#x2F;em&gt; are also inserted by the Rust compiler to detect &lt;em&gt;stack overflow&lt;&#x2F;em&gt;.
At present, this feature doesn&#x27;t apply to &lt;code&gt;#![no_std]&lt;&#x2F;code&gt; or other architectures - although &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;blog.japaric.io&#x2F;stack-overflow-protection&#x2F;&quot;&gt;creative linking solutions&lt;&#x2F;a&gt; have been suggested.
Stack probes, often implemented via guard pages, prevent exhausting stack space due to unending recursion.
Bounds checks, on the other hand, prevent stack or heap-based &lt;em&gt;buffer overflow&lt;&#x2F;em&gt; bugs.
It&#x27;s a subtle distinction, but an important one: for security, we typically care far more about the latter.&lt;&#x2F;p&gt;
&lt;p&gt;Keep in mind that memory, from the perspective of Rust, is a software abstraction.
When the abstraction ends, so do the guarantees.
If physical attacks (side-channel attacks, fault injection, chip decapsulation, etc.) are part of your threat model, there is little reason to believe that language choice offers any protection.
If you forgot to burn in the appropriate lock bits, shipped with a debug port exposed, and a symmetric key for firmware decryption&#x2F;authentication is sitting in &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;EEPROM&quot;&gt;EEPROM&lt;&#x2F;a&gt;: an attacker in the field won&#x27;t need a memory corruption bug.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;that-s-all-cool-but-how-about-day-to-day-development&quot;&gt;That&#x27;s all cool, but how about day-to-day development?&lt;&#x2F;h2&gt;
&lt;p&gt;Dependency management isn&#x27;t as glamorous as exploits with catchy marketing names or new-age compiler analyses to prevent them.
But if you&#x27;ve ever been responsible for production infrastructure, you know that patch latency is often the one metric that counts.
Sometimes it&#x27;s your code that is compromised, but more often it&#x27;s a library you rely on that puts your systems at risk.
This is an area where Rust&#x27;s package manager, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;&quot;&gt;&lt;code&gt;cargo&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, is invaluable.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;cargo&lt;&#x2F;code&gt; enables composability: your project can integrate 3rd-party libraries as statically-linked dependencies, downloading their source from a centralized repository on first build.
It makes dependency maintenance easier - including pulling the latest patches, security or otherwise, into your build.
No analogue in the C or C++ ecosystems provides &lt;code&gt;cargo&lt;&#x2F;code&gt;&#x27;s &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;reference&#x2F;specifying-dependencies.html&quot;&gt;semantic versioning&lt;&#x2F;a&gt;, but managing a set of &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;book&#x2F;en&#x2F;v2&#x2F;Git-Tools-Submodules&quot;&gt;git submodules&lt;&#x2F;a&gt; could have a similar effect.&lt;&#x2F;p&gt;
&lt;p&gt;Unlike C&#x2F;C++ submodule duck tape, the aforementioned composability is memory safe in Rust.
C&#x2F;C++ libraries pass struct pointers around with no enforced contract for who does the cleanup: your code might free an object the library already freed - a reasonable mistake - creating a new DF bug.
Rust&#x27;s ownership model provides a contract, simplifying interoperability across APIs.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, &lt;code&gt;cargo&lt;&#x2F;code&gt; provides first-class test support, an omission modern C and C++ are often criticized for.
Rust&#x27;s toolchain makes the &lt;em&gt;engineering&lt;&#x2F;em&gt; part of software engineering easier: testing and maintenance is straightforward.
In the real world, that can be as important for overall security posture as memory safety.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hold-on-didn-t-we-forget-about-integer-overflows&quot;&gt;Hold on...didn&#x27;t we forget about integer overflows?&lt;&#x2F;h2&gt;
&lt;p&gt;Not exactly.
Integer overflow isn&#x27;t a memory safety issue categorically, it&#x27;d almost certainly have to be part of a larger memory corruption bug chain to facilitate ACE.
Say the integer in question was used to index into an array prior to write of attacker-controlled data - safe Rust would still prevent that write.&lt;&#x2F;p&gt;
&lt;p&gt;Regardless, integer overflows can lead to nasty bugs.
&lt;code&gt;cargo&lt;&#x2F;code&gt; uses &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;cargo&#x2F;reference&#x2F;profiles.html&quot;&gt;configurable&lt;&#x2F;a&gt; build profiles to control compilation settings, integer overflow handling among them.
The default &lt;code&gt;debug&lt;&#x2F;code&gt; (low optimization) profile includes &lt;code&gt;overflow-checks = true&lt;&#x2F;code&gt;, so the binary output will panic on integer overflow where the developer hasn’t made it explicit (e.g. &lt;code&gt;u32::wrapping_add&lt;&#x2F;code&gt;).
Unless overwritten, &lt;code&gt;release&lt;&#x2F;code&gt; (high optimization) mode does the opposite: silent wrap-around is allowed, like C&#x2F;C++, because removing the check is better for performance.
Unlike C&#x2F;C++, &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;http:&#x2F;&#x2F;huonw.github.io&#x2F;blog&#x2F;2016&#x2F;04&#x2F;myths-and-legends-about-integer-overflow-in-rust&#x2F;&quot;&gt;integer overflow is not undefined behavior in Rust&lt;&#x2F;a&gt;; you can reliably expect two&#x27;s complement wrap.&lt;&#x2F;p&gt;
&lt;p&gt;If performance is priority number one, your test cases should strive for enough coverage of &lt;code&gt;debug&lt;&#x2F;code&gt; builds to catch the majority of integer overflows.
If security is priority number one, consider enabling overflow checks in &lt;code&gt;release&lt;&#x2F;code&gt; and taking the availability hit of a potential panic.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;takeaway&quot;&gt;&lt;span class=&quot;title-sub&quot;&gt;Takeaway&lt;&#x2F;span&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Memory safety is not a new idea, garbage collection and smart pointers have been around for a while.
But sometimes it&#x27;s the right implementation of an existing &lt;em&gt;good&lt;&#x2F;em&gt; idea that makes for a novel &lt;em&gt;great&lt;&#x2F;em&gt; idea.
Rust&#x27;s ownership paradigm - which implements an &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Substructural_type_system#Affine_type_systems&quot;&gt;affine type system&lt;&#x2F;a&gt; - is that great idea, enabling safety without sacrificing predictable performance.&lt;&#x2F;p&gt;
&lt;p&gt;Now I [begrudgingly] aim to be pragmatic, not dogmatic.
There are perfectly valid reasons to stick with a mature vendored &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Hardware_abstraction#In_operating_systems&quot;&gt;HAL&lt;&#x2F;a&gt; and C toolchain for a production embedded project.
Many existing C&#x2F;C++ code bases should be fuzzed, hardened, and maintained - not re-written in Rust.
Some library bindings, those of the &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ericpony.github.io&#x2F;z3py-tutorial&#x2F;guide-examples.htm&quot;&gt;z3 solver&lt;&#x2F;a&gt; being one example, greatly benefit from the dynamic typing of an interpreted language.
In certain domains, languages with &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Hoare_logic&quot;&gt;Hoare logic&lt;&#x2F;a&gt; pre and post conditions  might justify the productivity hit (e.g. &lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;SPARK_(programming_language)&quot;&gt;Spark Ada&lt;&#x2F;a&gt;).
Physical attacks are typically language agnostic.
In summary: no tool is a panacea.&lt;&#x2F;p&gt;
&lt;p&gt;That disclaimer aside, I can&#x27;t remember the last time a new technology made me stop and take notice quite like Rust has.
The language crystallizes systems programming best practices in the compiler itself, trading development-time cognitive load for runtime correctness.
Explicit opt-in (e.g. &lt;code&gt;unsafe&lt;&#x2F;code&gt;, &lt;code&gt;RefCell&amp;lt;T&amp;gt;&lt;&#x2F;code&gt;) is required for patterns that put memory at risk.
Mitigation of a major bug class feels like a legitimate shift left: a notable subset of exploitable vulnerabilities become compile time errors and runtime exceptions.
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;rustacean.net&#x2F;&quot;&gt;Ferris&lt;&#x2F;a&gt; has a hard shell.&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Read a free technical book!&lt;&#x2F;strong&gt;
I&#x27;m fulfilling a lifelong dream and writing a book.
It&#x27;s about developing secure and robust systems software.
Although a work-in-progress, the book is freely available online (no paywalls or obligations):
&lt;a rel=&quot;noopener&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;highassurance.rs&#x2F;&quot;&gt;https:&#x2F;&#x2F;highassurance.rs&#x2F;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
</content>
        
    </entry>
</feed>