# RUSTSEC-2026-0190: Unsoundness in `Error::downcast_mut()`

> Unsoundness in anyhow's downcast_mut allows undefined behavior and potential memory corruption when modifying error context.

- **Severity:** Not scored
- **Exploited in the wild:** Not known
- **Login needed:** Not needed
- **Attackable:** Not stated
- **Victim action needed:** Not needed
- **Fix available:** Yes
- **Published:** 25 Jun 2026

## What is RUSTSEC-2026-0190?

RUSTSEC-2026-0190 is a memory corruption vulnerability in anyhow, published on 25 Jun 2026. 

### Official description

Affected versions of this crate violate borrow rules, resulting in undefined behavior, when the user adds context to an error via `Error::context` and then later calls `Error::downcast_mut` on the returned `Error`.

The flaw was corrected in commit `6e8c000` by revising how the mutable reference is constructed, avoiding inclusion of a shared reference in the resulting borrow chain.

## Example

```rust
use anyhow::Error;
use std::fmt;

#[derive(Debug)]
struct ErrorContext(&'static str);

impl fmt::Display for ErrorContext {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        fmt::Display::fmt(&self.0, f)
    }
}

fn main() {
    let mut error = Error::msg("inner error").context(ErrorContext("old context"));
    let context: &mut ErrorContext = error.downcast_mut().unwrap();
    context.0 = "new context";
    println!("{:?}", error);
}
```

## Miri output

```
error: Undefined Behavior: trying to retag from <1538> for Unique permission at alloc602[0x38], but that tag only grants SharedReadOnly permission for this location
   --> src/ptr.rs:170:18
    |
170 |         unsafe { &mut *self.ptr.as_ptr() }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^ this error occurs as part of retag at alloc602[0x38..0x48]
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
help: <1538> was created by a SharedReadOnly retag at offsets [0x38..0x48]
   --> src/ptr.rs:89:18
    |
 89 |             ptr: NonNull::from(ptr),
    |                  ^^^^^^^^^^^^^^^^^^
    = note: stack backtrace:
            0: anyhow::ptr::Mut::<'_, ErrorContext>::deref_mut
                at src/ptr.rs:170:18: 170:41
            1: anyhow::error::<impl anyhow::Error>::downcast_mut::<ErrorContext>
                at src/error.rs:560:18: 560:46
            2: main
                at examples/downcast_mut.rs:15:38: 15:58
```

## Which versions are affected by RUSTSEC-2026-0190?

1 open source package ship an affected version, including anyhow.


| Package | Ecosystem | Affected | Fixed in |
| --- | --- | --- | --- |
| `anyhow` | crates.io | From 0.0.0-0 | 1.0.103 |

## How do I fix RUSTSEC-2026-0190?

Upgrade anyhow to 1.0.103 or later.

## Is RUSTSEC-2026-0190 being exploited?

There is no known exploitation of RUSTSEC-2026-0190 in the wild and no public exploit code.

## Fix prompt for AI coding agents

```text
Check this codebase for RUSTSEC-2026-0190 and fix it if it is affected.

What it is: RUSTSEC-2026-0190 is a memory corruption vulnerability in anyhow, published on 25 Jun 2026. 
Exploitation: There is no known exploitation of RUSTSEC-2026-0190 in the wild and no public exploit code.

Affected packages and fixed versions:
- anyhow (crates.io): affected from 0.0.0-0; fixed in 1.0.103

Task:
1. Search the dependency manifests and lockfiles (for example package.json, package-lock.json, requirements.txt, poetry.lock, uv.lock, pom.xml, build.gradle, go.mod, Cargo.lock, Gemfile.lock) and any Dockerfiles for the affected packages, including transitive dependencies.
2. If an affected version is in use, upgrade it to the fixed version for its release line with the project's package manager, so the lockfile is regenerated. Prefer the smallest upgrade that fixes it.
3. If there is no fix, or the upgrade would break the build, do not guess: explain the risk and the safest workaround instead.
4. Run the tests and summarise what changed and why.
5. If nothing in the project is affected, say so and change nothing.

Reference: https://insights.sbomify.com/RUSTSEC-2026-0190/ (Markdown: https://insights.sbomify.com/RUSTSEC-2026-0190/index.md)
```

## Sources

- OSV: https://osv.dev/vulnerability/RUSTSEC-2026-0190

---
From sbomify Insights: https://insights.sbomify.com/RUSTSEC-2026-0190/
Summaries are generated and may contain mistakes; the official description above is the record.
