If you are new to Rust and notice the version number has changed from <span>1.91.0</span> to <span>1.91.1</span>, a common reaction might be:
“Isn’t this just a minor patch? There probably isn’t much to see, right?”
However, the official Rust blog makes it clear: 1.91.1 is not about adding new features, but rather urgently fixing two regression issues introduced in 1.91.0, both related to Wasm and cargo target directory locking, which are low-level details that are often overlooked until something goes wrong.
This article will clarify:
- What two issues were fixed in 1.91.1?
- How are these issues related to “security” and “stability”?
- As a Rust beginner, should you care and upgrade?
First, the big picture: What two issues were fixed in 1.91.1?
According to the official blog post Announcing Rust 1.91.1, there are only two core fixes:
-
Regression issue with
<span>#[link(wasm_import_module)]</span>under the Wasm target
- This could lead to a link-time error:
<span>"import module mismatch"</span>; - Worse, at runtime, it could result in “calling the wrong function”, leading to undefined behavior, including crashes and silent data corruption.
Failure of Cargo’s <span>target/</span> directory lock on the illumos platform
- Due to the standard library’s
<span>File::lock</span>always returning<span>Unsupported</span>on illumos; - This led Cargo to mistakenly believe that “locking is not supported here”, resulting in no locks during builds;
- When multiple builds run simultaneously, they could interfere with each other’s outputs.
These issues may sound low-level and niche, but they are directly related to either “security boundaries potentially being bypassed” or “build results becoming uncertain”, both of which are crucial for stability and security.
1. The Wasm issue: Same-named functions were “confused”
1. How does Wasm recognize a function?
On most common platforms (Linux / macOS / Windows), a symbol (function) is typically identified by its “name”, such as <span>foo</span> or <span>bar</span>.
However, in WebAssembly (Wasm), imported functions generally have two layers of information:
- Module name: can be roughly understood as the “folder name”;
- Symbol name: akin to the “file name” within that folder.
In the same <span>world</span>, if they come from module <span>hello</span> and module <span>auth</span>, they are actually two completely different logics.
In Rust, if you want to import a function from a Wasm module, you typically write it like this:
#[link(wasm_import_module = "hello")]\nextern "C" {\n pub fn world();\n}
Here:
<span>#[link(wasm_import_module = "hello")]</span>tells the compiler:- “This function in the
<span>extern</span>block is imported from the Wasm module<span>hello</span>.” <span>world</span>is the specific function name.
What truly identifies this function is the combination of (module name = “hello”, symbol name = “world”).
2. The regression in 1.91.0: Link errors and potential wrong function calls at runtime
The official Rust description states:
Rust 1.91.0 introduced a regression with this attribute, where importing same-named functions from different Wasm modules, scattered across multiple crates, could lead to:
- Linking errors with
<span>"import module mismatch"</span>;- Or more insidiously: compiling successfully, but at runtime, it secretly called the wrong function implementation.
For a relatively “safe” example:
- Module
<span>auth</span>has a<span>check</span>function responsible for permission verification; - Module
<span>log</span>also has a<span>check</span>function, which only logs messages; - Different crates import
<span>check</span>from<span>auth</span>and<span>log</span>using<span>#[link(wasm_import_module = "...")]</span>.
If the bug in 1.91.0 is triggered:
- You think you are calling
<span>auth::check</span>for security verification; - But at runtime, it actually calls
<span>log::check</span>, which only logs a message and does not verify any permissions.
The official blog directly mentions that such issues could lead to:
- Undefined behavior;
- Including but not limited to:
- Program crashes;
- Silent data corruption;
- Logical security checks being quietly bypassed.
3. Where is the “security risk” here?
Many people associate Wasm with keywords like “sandbox, isolation, memory safety” and think it should be very secure.
From a memory safety perspective, Wasm indeed has inherent advantages; however, this issue is more about “business logic security”:
- If what you do in Wasm includes:
- Authentication / Authorization;
- Request filtering / Risk control;
- Pre-checks before sensitive operations (like payments, password changes);
- Once a “wrong function is called”, the results could be:
- The check was not performed;
- The denial was not executed;
- Or incorrect data was processed, resulting in completely unreliable outcomes.
What’s more troublesome is:
This kind of bug is hard to expose immediately in a development environment because it requires a combination of “multiple crates + multiple modules + same-name imports”.Real issues often occur in complex production environments where a specific deployment method happens to hit this combination.
4. What exactly was fixed in 1.91.1?
In simple terms:
- After the fix, the compiler/linker will correctly distinguish
<span>(module name, symbol name)</span><code><span>;</span> - There will no longer be confusion with imports of same-named functions from different modules;
- This also prevents the issue of “secretly calling the wrong function” at runtime.
2. Cargo lock failure on illumos: Builds stepping on each other
The second issue occurs on the illumos platform (a Solaris-like system, which, although not widely used, still has users in certain scenarios).
1. Why does Cargo lock the <span>target/</span> directory?
When you run <span>cargo build</span>, all intermediate products and final binaries are typically placed in the <span>target/</span> directory.
If you:
- Run two
<span>cargo build</span>commands simultaneously; - Or if your IDE is quietly compiling in the background while you manually run it in the foreground;
They may read and write to the same set of files. Without control, this could lead to:
- One build writing a file halfway while another build has already started reading it;
- Multiple builds overwriting and deleting each other’s outputs.
To prevent this, Cargo attempts to create a “lock” on the <span>target/</span> directory during builds:
- If the lock is successful: it indicates that this build has “gained usage rights”, and other builds must either wait or fail;
- If the operating system explicitly states “locking is not supported”, Cargo will choose to not lock, but will try to avoid pitfalls.
2. The change in 1.91.0: Switching from self-developed locks to <span>File::lock</span>
Before Rust 1.91.0, Cargo used its own locking logic that interacted with the system API.In 1.91.0, the official team made a seemingly healthy refactor:
Replacing the original custom locking logic with the new stable
<span>File::lock</span>methods from the standard library (stabilized in 1.89.0).
This change itself is fine,but the problem lies on illumos:
- Due to an oversight,
<span>File::lock</span>always returns Unsupported on the illumos target; - When Cargo receives this return value, it assumes “this file system does not support locking”, and thus:
- It no longer performs any locking operations;
- Regardless of whether the actual file system supports locking.
The result is:
On illumos, no matter how many
<span>cargo build</span>commands you run in parallel, Cargo will not prevent them from stepping on each other in the<span>target/</span>directory.
3. What consequences could this have?
If you are on illumos:
- Using a shared
<span>target/</span>build method; - Running multiple builds/tests/CI tasks simultaneously;
Theoretically, this could lead to:
- Intermediate products being overwritten by another build;
- A build reading a “half-written” file;
- The final generated binary being in a “strange state that is hard to reproduce”:
- Sometimes running normally, sometimes crashing inexplicably;
- Some bugs that do not appear locally but only in CI or production.
4. Is this a security issue?
This issue is more about “build safety / supply chain reliability”, rather than a vulnerability that is obviously a remote attack vector.
However, if you consider it from the perspective of “reproducible experiments + deterministic builds”, it does have risks:
- The built program is no longer a deterministic product, carrying a certain “Schrödinger’s state”;
- In highly automated CI/CD pipelines:
- You think the tested and deployed binary is the same, but it may not be;
- Some bugs only trigger in production, making it hard to correlate with source code and build logs.
The fix in 1.91.1 is:
- Fixing the issue where
<span>File::lock</span>always returns<span>Unsupported</span>on the illumos target in the standard library; - Making
<span>File::lock</span>truly usable on illumos; - Thus, Cargo can again properly lock the
<span>target/</span>directory on illumos, indirectly fixing the regression.
3. Why is version 1.91.1 worth upgrading to, despite being a “minor version”?
First, let’s categorize the two issues:
-
Wasm regression
- Impacted users: Projects using
<span>#[link(wasm_import_module)]</span>and importing same-named functions across multiple crates; - Risk type: Runtime calling of the wrong function, leading to undefined behavior;
- Potential consequences: Crashes, data corruption, business security logic being quietly bypassed.
-
illumos + Cargo regression
- Impacted users: Users developing, running CI, or production builds on illumos;
- Risk type: Builds stepping on each other, leading to uncertain outputs;
- Potential consequences: Hard-to-reproduce build bugs, inconsistencies between local and production.
The commonality is:
Both are regressions introduced in 1.91.0, not “old bugs finally fixed”.
In other words:
- You might not have issues on 1.90.x or even earlier versions;
- It is only after upgrading to 1.91.0 that you might encounter these pitfalls;
- The role of 1.91.1 is more like:
- “Restoring the quality that 1.91.0 should have had.”
From an engineering practice perspective,minor versions specifically fixing regressions are generally worth upgrading quickly because:
- They are not risking adding features but are helping youreduce the probability of strange issues;
- Even if you are not encountering issues now, it is hard to guarantee that future dependency upgrades or deployment method changes won’t trigger such corner cases.
4. What should I do if I am a beginner?
If you are just starting with Rust and writing small demos, you might think:
“These two issues sound pretty far from me, should I care?”
I would recommend at least doing three simple things:
1. Check your current version
rustc --version\n
If you see <span>1.91.0</span>, I strongly recommend upgrading; if you are on an even older version, consider upgrading to the latest stable version as well.
2. Upgrade to the latest stable version using <span>rustup</span>
The official recommended way is very simple:
rustup update stable\n
If you haven’t installed <span>rustup</span> yet, you can install it from the official website:
- https://www.rust-lang.org/tools/install
3. Even if you currently do not use Wasm and illumos, it is advisable to follow the stable version
The reasons are practical:
- You will likely encounter Wasm in the future (frontend integration, cloud functions, edge computing, etc.);
- Most maintainers of CI/CD, third-party libraries, and various tools will use the latest stable version as a reference baseline;
- Being on a version without these regressions can save you a lot of troubleshooting time in the future.
4. If you are a maintainer, pay special attention to these scenarios
- If your project uses
<span>#[link(wasm_import_module)]</span>and may import same-named functions across crates: - After upgrading to 1.91.1, rerun the critical paths;
- Try to clarify the import logic for “security, validation, encryption” type logic.
- If you are running builds/tests/production on illumos:
- After upgrading, check if any previously intermittent build issues have been “quietly fixed”;
- If possible, separate the
<span>target/</span>directory for large projects (e.g., split by workspace or configuration) to further reduce the possibility of mutual interference.
5. Summarizing the “security significance” of this update in one sentence
Finally, let me compress it into a memorable point:
-
For Wasm: The fix addresses the issue of the combination of “import module + symbol name” being confused, leading to wrong function calls,
- If the affected logic is security-related, it could evolve into a “logical security” risk.
-
For illumos: The fix addresses the issue of
<span>File::lock</span>not working on illumos, - Which in turn led to Cargo not locking the
<span>target/</span>directory, resulting in uncertain build outputs.
So, to put it in a more relatable way:
Rust 1.91.1 is the kind of version that “looks like just a minor increment, but is actually fixing critical underlying details”. You don’t need to understand all the implementations, but at least don’t stay stuck on 1.91.0.
References and Further Reading
If you want to dive deeper, you can start with these official resources and issues:
- Rust Official Blog: Announcing Rust 1.91.1
- https://blog.rust-lang.org/2025/11/10/Rust-1.91.1/
- Rust Reference:
<span>#[link(wasm_import_module)]</span>attribute description - https://doc.rust-lang.org/reference/items/external-blocks.html#r-items.extern.attributes.link.wasm_import_module
- Rust Standard Library Documentation:
<span>File::lock</span>and file locks - https://doc.rust-lang.org/stable/std/fs/struct.File.html#method.lock
- Rust GitHub Issue: Wasm import module regression issue (issue #148347)
- https://github.com/rust-lang/rust/issues/148347
- Rust Official: Security Policies & Disclosure
- https://www.rust-lang.org/policies/security