Rust 1.0 shipped on 15 May 2015, and since that day a new stable version has left the station every six weeks, with beta and nightly channels running ahead of it and no long term support line behind it. Breaking language changes arrive only through opt in editions (2015, 2018, 2021 and 2024, the last one stabilized in Rust 1.85.0 on 20 February 2025), and the project's security team ships fixes only for the newest stable release.
Those three facts shape almost every practical decision a Rust team makes: how to pin a toolchain, how to declare a minimum supported version, when to move editions, and how fast to take a point release. This post walks through the history behind each of them. It covers the prehistory before 1.0, how the release train works week by week, what an edition can and cannot change, a dated table of the releases that mattered, how governance moved from a Mozilla research project to the Rust Foundation and the Leadership Council, and how the Rust Security Response team handles vulnerabilities in the compiler, Cargo and the standard library. Every version and date below was checked against the project's own RELEASES.md, the Rust blog, the Edition Guide, the Rust Forge, the rustup book or the Rust security policy. The current stable at the time of writing is Rust 1.99.1, released on 15 October 2026.
If you are planning an edition move right now, read our companion post on Rust edition migration security notes for the migration itself; this post stays on the history and the release mechanics.
Key takeaways
- 1.0 was a stability promise, not a finish line. The Rust core team called the 15 May 2015 release the "official beginning of our commitment to stability", and released Rust 1.1 beta the same day to start the six week train.
- Three channels, one cadence. Nightly builds every night, beta is the next stable in testing, and stable ships every six weeks with occasional point releases. As of October 2026 there have been 99 minor stable releases since 1.0.
- There is no LTS. The security policy says the project supports only the most recent stable release plus the latest beta and nightly. A toolchain pinned to an old stable gets no backported fixes.
- Editions are opt in, per crate, and interoperable. A 2015 edition crate and a 2024 edition crate link together in one build. Editions can reserve keywords, change lints and adjust some semantics, but they cannot split the ecosystem or change how compiled crates talk to each other.
- Governance changed twice in three years. Mozilla announced plans for an independent Rust Foundation in August 2020; the Foundation was operating by early 2021. On 20 June 2023 RFC 3392 created the Leadership Council, replacing the Core Team.
- Security fixes are real and recurring. Memory safety removes whole classes of bugs, but the toolchain and standard library still receive advisories: Windows argument escaping in
std::process::Command(CVE-2024-24576), aremove_dir_allrace (CVE-2022-21658), several Cargo issues in 2026, and more. - rustup downloads over HTTPS but does not yet check signatures. The rustup book says so directly. If you need signature verification, the standalone installers carry GPG signatures from the Rust signing key.
How did Rust begin?
From a personal project to Mozilla Research
The Rust core team's own account, published in August 2020, says the project was first conceived as a Mozilla Research project in 2010, or in 2006 depending on how you count. The 2006 date in that post links to the first commit in Graydon Hoare's rust-prehistory repository, which preserves the language's earliest history before Mozilla took it on as a sponsored research project. The same post describes Mozilla as a steady financial and legal sponsor through the years that followed.
The 0.x years, 2012 to 2014
Rust's public version history in RELEASES.md starts with Version 0.1 on 20 January 2012. Releases arrived every few months after that: 0.2 on 29 March 2012, 0.4 on 15 October 2012, 0.5 on 21 December 2012, 0.6 on 3 April 2013, 0.7 on 3 July 2013, 0.8 on 26 September 2013, 0.9 on 9 January 2014, 0.10 on 3 April 2014, 0.11.0 on 2 July 2014 and 0.12.0 on 9 October 2014.
The language changed a great deal in these years. Features came and went, the runtime model changed, and the standard library was rewritten more than once. The Rust 1.0 announcement is frank about the cost: with the language and standard library changing constantly, projects written in Rust were hard to maintain.
Alphas, the RFC process and 1.0
Two pre releases led into 1.0: 1.0.0 alpha on 9 January 2015 and 1.0.0 alpha.2 on 20 February 2015. By then the project had already adopted the RFC (Request for Comments) process, under which every major decision is written up and discussed in the open, and a new governance model with subteams responsible for RFCs in their area.
RFC 507 set out the release model that would follow 1.0: time based releases split into channels on the "release train" model used by browsers, plus feature staging so unstable features could keep developing on nightly without weakening the guarantees of stable.
Rust 1.0.0 shipped on 15 May 2015. The announcement made three points that still define the project:
- From 1.0 on, breaking changes were mostly off the table, with minor caveats such as compiler bugs.
- Releases would follow a train model with a new version every six weeks, as the major web browsers do, and Rust 1.1 beta was released alongside 1.0 to start the train.
- Cargo, the build tool and package manager, and crates.io, the central package registry, were part of the release story from day one.
The Edition Guide later summarized the principle that 1.0 established as "stability without stagnation": once a feature reaches stable, it is supported in every future release.
How do Rust release trains work?
Nightly, beta and stable
The Rust book's appendix on how Rust is made describes the model in railway terms. All development happens on the main branch of the rust-lang/rust repository. Every night the release infrastructure builds a nightly toolchain from that branch automatically. Every six weeks the beta branch forks from main, and the previous beta becomes the new stable release.
So at any moment there are three trains in motion:
- Nightly carries everything merged so far, including unstable features behind
#![feature(...)]gates that only nightly accepts. - Beta is the next stable release in its six week testing window. It receives only backported fixes.
- Stable is what most people should build with. It changes every six weeks, plus point releases when something is badly broken or a security fix cannot wait.
The rustup book sums it up the same way: stable every six weeks, with an occasional point release in between. It also notes that rustup can install specific versions such as 1.45.2 or dated nightlies such as nightly-2020-07-27.
What release week looks like
The Rust Forge publishes the release team's runbook, and it shows how mechanical the train is. The version number on main is bumped on the Friday before release week; that bump is effectively when the new beta forks. On Monday the release team promotes branches: the beta branch becomes the new stable branch and main becomes the new beta. They copy in the final release notes, check for beta backports that were approved but not yet merged, and push a pre release to a staging environment for testing. On Tuesday, once the new beta has built (beta builds run automatically at 00:00 UTC every day), they update the compiler's bootstrap toolchain on main and can start the next cycle's large scale ecosystem test runs. Release day is Thursday, and the runbook notes that as of September 2024 a release took between 75 and 90 minutes to complete.
That predictability is useful for planning. You can work out the next few stable dates by adding six weeks to the last one. The five most recent minor releases in RELEASES.md fall exactly six weeks apart: 1.95.0 on 16 April 2026, 1.96.0 on 28 May 2026, 1.97.0 on 9 July 2026, 1.98.0 on 20 August 2026 and 1.99.0 on 1 October 2026.
No LTS, by design
Many runtimes offer long term support lines: a version that receives security fixes for years while new features land elsewhere. Rust does not. The Rust security policy states that the project supports and ships security updates for the most recent stable release only, along with the latest beta and nightly builds.
This is the single most important fact for anyone writing a toolchain policy. When Rust 1.96.0 shipped on 28 May 2026 with the fixes for CVE-2026-5222 and CVE-2026-5223 in Cargo, the advisories said plainly that older Cargo versions would not get a fix. For CVE-2026-5222 the advisory says "No mitigations are available for users of older versions of Cargo." The only supported path was to move to 1.96.0 or later.
The trade off is that moving forward is designed to be cheap. Stable releases are meant to be backwards compatible, and the project runs its compiler against a large share of the public crate ecosystem before each release to catch regressions. Linux distributions and some vendors do maintain their own longer lived Rust packages, but those are the distributor's commitment, not the Rust project's.
What this means for pinning
Pinning a toolchain is still a good idea. Reproducible builds and predictable CI need it. The point is to pin to a specific stable and then move the pin forward on a schedule, not to pin once and forget. Two separate settings do two separate jobs:
| Setting | File | What it controls | Who it affects |
|---|---|---|---|
channel in [toolchain] | rust-toolchain.toml | The exact toolchain rustup uses in this directory | Everyone who builds this repository, including CI |
rust-version | Cargo.toml | The oldest Rust your package claims to support (the MSRV) | Downstream users of your crate, and Cargo's resolver |
edition | Cargo.toml | Which edition's rules this crate compiles under | Only this crate |
The rustup book says rust-toolchain.toml is "suitable to check in to source control", and that if you pin to a specific release you should probably commit Cargo.lock too. The Cargo reference says the rust-version field has been respected since 1.56: building on an older toolchain fails with a clear error, unless the user passes --ignore-rust-version.
Rust release channels at a glance
| Channel | Cadence | Support from the Rust project | Who should use it |
|---|---|---|---|
| Stable (latest) | Every six weeks, plus point releases | Security updates and fixes | Production builds, CI release jobs, most developers |
| Stable (older versions) | Frozen once superseded | None. No backports | Only as a temporary pin while you test the next stable |
| Beta | Rebuilt daily, becomes stable after six weeks | Latest beta only | CI jobs that test your code against the next release early |
| Nightly | Every night | Latest nightly only | Unstable features, compiler and tool development, experiments; never as an unpinned production dependency |
Dated nightly (for example nightly-2026-10-01) | Fixed snapshot | None once a newer nightly exists | Projects that truly need an unstable feature and pin a known good nightly |
What are Rust editions?
The problem editions solve
RFC 2052 introduced the idea in 2017 under the name "epochs" and proposed declaring an edition every two or three years. Editions are named for the year they appear and, in the RFC's words, act as a "rallying point" for a coherent set of features, polished error messages, updated tooling and documentation.
The Edition Guide explains the practical need with a simple example. Early Rust had no async or await keywords. Making them keywords overnight would have broken any code that used async as a variable name. Editions solve that: backwards incompatible changes go into the next edition, and because editions are opt in, existing crates keep compiling exactly as before until their authors choose to migrate.
Each crate picks its edition in Cargo.toml. If the field is missing, Cargo assumes 2015 for backwards compatibility. cargo new writes the newest stable edition, which today is 2024.
What editions can change
Across the four editions so far, edition changes have included:
- New keywords:
asyncandawaitbecame keywords in 2018;genis reserved in 2024. - Lint levels: warnings that become errors, or new lints that warn by default. In 2024,
unsafe_op_in_unsafe_fnwarns by default and references tostatic mutare denied by default. - Some semantics, carefully: 2021 changed closures to capture individual fields rather than whole variables (disjoint capture); 2024 changed the scope of temporaries in
if letand in tail expressions, which changes drop order. - The prelude: 2021 added
TryFrom,TryIntoandFromIterator; 2024 addedFutureandIntoFuture. - Which functions are
unsafe: in 2024,std::env::set_var,std::env::remove_varand the UnixCommandExt::before_execbecame unsafe to call. - Tool defaults: 2021 made Cargo's feature resolver version 2 the default; 2024 made Cargo's dependency resolver consider
rust-versionby default, and introduced rustfmt "style editions".
What editions cannot change
The Edition Guide names this as the most important rule of all: crates in one edition must interoperate with crates compiled under other editions. Each crate decides when to migrate, and that decision is private to the crate. The guide explains that this limits edition changes to fairly shallow ones, because all Rust code, regardless of edition, compiles down to the same internal representation in the compiler.
That rule has consequences worth knowing:
- An edition cannot remove a standard library API. The library is shared by every edition in a build.
- An edition cannot change the ABI or how two crates call each other.
- An edition does not pin your compiler version. A 2015 edition crate built with Rust 1.99.1 gets every compiler fix in 1.99.1.
- Moving editions does not, by itself, fix any security vulnerability, and staying on an old edition does not keep you on an old, vulnerable compiler.
Every edition so far
| Edition | Stabilized in | Release date | Headline changes |
|---|---|---|---|
| 2015 | Rust 1.0.0 | 15 May 2015 | The default when edition is not set; everything up to 2018 |
| 2018 | Rust 1.31.0 | 6 December 2018 | edition key in Cargo.toml; non lexical lifetimes; module system changes; async and await reserved as keywords |
| 2021 | Rust 1.56.0 | 21 October 2021 | Disjoint closure capture; IntoIterator for arrays; Cargo feature resolver 2 by default; panic macros always take format strings; prelude additions |
| 2024 | Rust 1.85.0 | 20 February 2025 | unsafe extern blocks and unsafe attributes; static mut references denied; temporary scope changes; gen reserved; Rust version aware resolver; style editions |
The Rust 1.31 announcement called it "the most exciting release since Rust 1.0", and the 1.85.0 announcement described 2024 as "the largest edition we have released." The migration tool, cargo fix --edition, makes conservative changes that preserve behaviour; the 1.85 announcement warns that its output is not a recommendation, because in some places you may prefer the new semantics instead.
Timeline: the stable releases that mattered
Ninety nine minor stable releases is too many to list. The table below picks the ones that changed how people write, build or secure Rust, with dates from RELEASES.md and the release announcements.
| Version | Date | Why it matters |
|---|---|---|
| 0.1 | 20 January 2012 | First numbered public release in RELEASES.md |
| 1.0.0 alpha | 9 January 2015 | First 1.0 pre release |
| 1.0.0 | 15 May 2015 | Stability promise; six week train starts; Cargo and crates.io part of the launch |
| 1.27.1 | 10 July 2018 | Point release for a rustdoc plugin loading vulnerability (CVE-2018-1000622) |
| 1.29.1 | 25 September 2018 | Point release fixing an out of bounds write in str::repeat caused by integer overflow |
| 1.31.0 | 6 December 2018 | Rust 2018 edition; non lexical lifetimes; const fn |
| 1.34.2 | 14 May 2019 | Destabilized Error::type_id over a security issue (CVE-2019-12083) |
| 1.39.0 | 7 November 2019 | async and .await stable |
| 1.51.0 | 25 March 2021 | Const generics MVP; Cargo's new feature resolver available |
| 1.56.0 | 21 October 2021 | Rust 2021 edition; rust-version field in Cargo.toml |
| 1.56.1 | 1 November 2021 | Lints against bidirectional Unicode override characters (CVE-2021-42574) |
| 1.58.1 | 20 January 2022 | Fix for a race in std::fs::remove_dir_all (CVE-2022-21658) |
| 1.65.0 | 3 November 2022 | Generic associated types; let/else |
| 1.66.1 | 10 January 2023 | Cargo validates SSH host keys for git URLs (CVE-2022-46176) |
| 1.68.0 | 9 March 2023 | Sparse registry protocol stable in Cargo |
| 1.68.2 | 28 March 2023 | New GitHub RSA host key bundled in Cargo; old one marked revoked after it leaked |
| 1.71.1 | 3 August 2023 | Cargo respects umask when extracting dependencies (CVE-2023-38497) |
| 1.77.2 | 9 April 2024 | Windows batch file argument escaping in std::process::Command (CVE-2024-24576) |
| 1.81.0 | 5 September 2024 | Completes the 1.77.2 fix for batch file names with trailing spaces or periods (CVE-2024-43402) |
| 1.85.0 | 20 February 2025 | Rust 2024 edition; async closures |
| 1.94.1 | 26 March 2026 | Cargo updates its tar dependency (CVE-2026-33055 and CVE-2026-33056) |
| 1.95.0 | 16 April 2026 | Patches for two vulnerabilities applied to the vendored musl C library |
| 1.96.0 | 28 May 2026 | Cargo fixes for registry URL normalization (CVE-2026-5222) and tarball symlinks (CVE-2026-5223) |
| 1.96.1 | 30 June 2026 | Cargo applies patches for three libssh2 CVEs |
| 1.99.1 | 15 October 2026 | Current stable at the time of writing; fixes a miscompilation of FFI bool returns on x86_64 |
A pattern stands out. The security relevant point releases rarely touch the borrow checker or the core memory model. They land in the places where Rust meets the outside world: Windows process spawning, file system operations, SSH and git, tar extraction, and vendored C libraries such as musl, OpenSSL and libssh2.
Two other kinds of point release deserve attention too. Miscompilation fixes, such as 1.80.1 (a jump threading optimization bug when comparing floats), 1.97.1 (an LLVM optimization bug) and 1.98.1 (vtable generation), are not filed as security advisories, but a compiler that generates wrong code can break safety guarantees in a shipped binary. And 1.52.1 on 10 May 2021 disabled incremental compilation by default after newly added verification exposed bugs that, the release notes warn, "can lead to miscompilation".
How is the Rust project governed?
The RFC process and the teams
The Rust governance page says each major decision "starts as a Request for Comments (RFC)" that anyone can discuss. Work is split among teams: compiler, dev tools, infrastructure, language, library, moderation, release, crates.io and others. The 1.0 announcement presented the move to subteams as a step toward more open, community driven governance.
From Mozilla to the Rust Foundation
On 11 August 2020 Mozilla announced a restructuring that laid off around 250 people, including people active in the Rust project. A week later, on 18 August 2020, the Rust core team published "Laying the foundation for Rust's future". It made two points. First, the project had run its own direction and governance independently of Mozilla since 1.0, with Mozilla as a sponsor. Second, the core team and Mozilla announced plans to create a Rust foundation, with the goal of having the first iteration "up and running by the end of the year." Its first task would be to take ownership of the trademarks and domain names that Mozilla had held.
By the project's sixth anniversary post on 15 May 2021, the blog was referring to "the newly founded Rust foundation" with member companies supporting the project. The Foundation is a separate non profit that took over the trademarks and domain names, and RFC 3392 makes the Leadership Council responsible for selecting the Project directors who represent the Rust Project on its board. On 2 June 2026 the Rust blog explained how the Rust Foundation Maintainers Fund would support project maintainers, through RFC 3931, a new Funding team and a Maintainer in Residence program. The Foundation does not decide language design or what goes into a release; those decisions stay with the project's teams.
From the Core Team to the Leadership Council
The second change came in 2023. On 20 June 2023 RFC 3392 was merged, creating the Leadership Council as the project's top level governance body. The announcement says the Council "marks the end of both the Core Team and the interim Leadership Chat." Each top level team chose one representative: compiler, crates.io, dev tools, infrastructure, language, launching pad (a temporary umbrella for teams without a top level home), library, moderation and release.
RFC 3392 sets out what the Council does and does not do. It handles project wide concerns and operational decisions, communicates official positions, and runs the process for selecting the Project directors who sit on the Rust Foundation board. Technical decisions about the compiler, language, library and tools remain with the teams. The RFC also includes term limits and limits on how many representatives can come from a single company.
For a security or platform team, the practical meaning is stability of process. Release cadence, the RFC process and the security policy did not change when governance did.
Who handles security in Rust?
Three different groups matter, and it helps to know which one to watch for which problem.
| Problem | Who handles it | Where it is published |
|---|---|---|
| Vulnerability in rustc, Cargo, rustup, the standard library or official rust-lang crates and services | Rust Security Response team | Rust blog, the security announcements mailing list, CVE records, GitHub advisories |
| Vulnerability in a third party crate on crates.io | The crate's maintainers; tracked by the community RustSec Advisory Database | rustsec.org, RUSTSEC identifiers, cargo audit |
| Malicious or compromised crates on crates.io, registry abuse | crates.io team, with the security response team | Rust blog posts and crates.io policies |
The Rust Security Response team and its scope
The security policy asks reporters to email security@rust-lang.org. Reports are acknowledged within 24 hours, with a more detailed response within 48 hours, and updates at least every five days while a fix is prepared. The policy names the security coordinators directly as an escalation path.
The scope is broad: everything in the rust-lang, rust-lang-ci, rust-lang-nursery and rust-analyzer GitHub organizations, the rust-lang.org, rustup.rs, crates.io, docs.rs and rfcbot.rs domains, crates owned by the rust-lang-owner account, and the project's editor extensions. Third party crates on crates.io are out of scope and follow crates.io's own security policy.
One line in the policy matters for threat modelling. Unless noted otherwise, every toolchain component assumes your source code and dependencies are fully trusted and reviewed, and the project does not count "attacks caused by compiling or analyzing malicious projects or dependencies" as security vulnerabilities. In practice that means cargo build on an untrusted repository is running untrusted code (build scripts and procedural macros run at compile time), and no rustc release will treat that as a bug. Isolation for untrusted builds is your job.
Soundness bugs in the compiler are not automatically treated as vulnerabilities either; the policy says they are analysed case by case.
RustSec and cargo audit
RustSec is the community advisory database for crates. Its site describes cargo-audit as a tool to "Audit Cargo.lock files for crates with security vulnerabilities", and lists related tools: cargo-deny for policy checks on licenses, sources and duplicate versions, and cargo-auditable, which embeds the dependency tree into compiled binaries so they can be audited later. Advisories get RUSTSEC identifiers and many also carry CVE or GHSA aliases. Our post on cargo audit for Rust dependencies covers the tool in depth.
crates.io: trusted publishing and incident response
crates.io added trusted publishing in 2025, as described in RFC 3691. The July 2025 crates.io development update says it "eliminates the need for GitHub Actions secrets" when publishing from CI: you configure which GitHub repository is trusted on crates.io, and that workflow requests a short lived token through OpenID Connect. The RFC notes that such tokens are typically valid for less than an hour. At launch it supported GitHub Actions only, and the first release of a crate still had to be published manually.
The registry's incident handling is visible on the Rust blog. On 20 August 2026 the security response team published a post about a supply chain attack in which a malicious crate with a build script that downloaded a payload was reported, and the popular arrayref crate had been republished to depend on it. The team deleted the malicious crates and versions (the post lists each with its publish and delete times; the malicious arrayref 0.3.10 was online for 86 minutes), restored versions that had been maliciously yanked, and locked the affected account. The post includes a find command to check ~/.cargo/registry/cache for the deleted files. Earlier, in March 2026, the crates.io team blocked uploads that exploited the tar vulnerability (CVE-2026-33056) before the Cargo fix shipped, and audited every crate ever published.
How are toolchain and standard library fixes released?
The five step disclosure process
The security policy lays out five steps:
- A report is received and assigned a primary handler, who coordinates the fix and release.
- The problem is confirmed, affected versions are identified, and experts from the relevant teams are brought in.
- Code is audited for similar problems.
- Fixes are prepared for all supported release branches and a CVE is reserved. The fixes stay in private repositories and are reviewed privately.
- On the embargo date the announcement goes to the security mailing list and the Rust blog, the changes are pushed publicly, and the release process starts. Full details go into the CVE database within an hour.
Because Rust releases must be built in public, the policy says the release process starts as soon as the embargo lifts, and the release post appears once binaries are available. When a vulnerability affects distributions, the project notifies the distros list at Openwall 72 hours before the embargo lifts.
Two delivery patterns
In practice fixes arrive in one of two ways.
A point release on embargo day. CVE-2024-24576 is the clearest example. The advisory went out on 9 April 2024 and Rust 1.77.2 shipped "later today". The issue: on Windows, std::process::Command did not escape arguments thoroughly enough when invoking .bat or .cmd files, because cmd.exe splits arguments with its own rules. With untrusted arguments, the advisory rated it critical. The fix improved the escaping and made Command return an InvalidInput error when it cannot escape an argument safely. Five months later CVE-2024-43402 (low severity) covered an incomplete part of that fix, for batch file names with trailing whitespace or periods, fixed in 1.81.0.
An advance advisory pointing at the next scheduled release. For CVE-2026-5222 and CVE-2026-5223, both published on 25 May 2026, the advisories announced that Rust 1.96, due three days later on 28 May 2026, would contain the fixes. CVE-2026-5222 (low severity) affected Cargo versions from Rust 1.68 to 1.96 and could leak a registry token between registries hosted on the same domain under narrow conditions. CVE-2026-5223 (medium for third party registry users) let a crafted tarball with symlinks overwrite another crate's cached source; crates.io was not affected because it already rejects symlinks. For the tar issue in March 2026, the advisory on 21 March announced Rust 1.94.1 for 26 March and noted that the crates.io side had been mitigated on 13 March.
Where to watch
- The Rust blog, which carries both release announcements and security advisories.
- The Rust security announcements mailing list, which carries little traffic and receives notices the moment an embargo lifts. Announcements are signed with the Rust security key.
RELEASES.mdinrust-lang/rust, which lists CVE fixes in each version's notes, including fixes for vendored C libraries that never get their own blog post (for example the musl patches in 1.95.0 and the libssh2 patches in 1.96.1).- The GitHub security advisories pages of
rust-lang/rustandrust-lang/cargo.
How downloads are verified
This part is often assumed rather than checked. The rustup book's security page says rustup "performs all downloads over HTTPS, but does not yet validate signatures of downloads." Transport security protects the download in transit; it does not prove the file is the one the release team signed.
If you need signature verification, the Rust Forge's "Other installation methods" page lists standalone installers for every target. Each one is signed with GPG using the Rust signing key, published at static.rust-lang.org/rust-key.gpg.ascii and on keybase.io, with .asc signature files alongside. The distribution server also publishes .sha256 files for the standalone tarballs, for the channel manifests and for rustup-init itself.
One more rustup detail affects CI. rustup 1.28.0 (2 March 2025) stopped installing the active toolchain automatically; rustup 1.28.1 two days later turned automatic install back on by default, with RUSTUP_AUTO_INSTALL=0 to opt out. Running rustup toolchain install with no arguments installs whatever toolchain the directory's rust-toolchain.toml names, on both behaviours.
Step by step: pin, declare, audit and update
Step 1: find out what you are running
rustc -V
rustc -vV # adds commit hash, host triple and LLVM version
cargo -V
rustup show # installed toolchains and which one is active here, and why
rustup toolchain list
rustup show reports why a toolchain is active: a directory override, a rust-toolchain.toml file or the default. Run it inside each repository, not only in your home directory.
Then compare the version against the newest stable on the Rust blog or in RELEASES.md. Anything older than the latest stable is, by the security policy, unsupported.
Step 2: pin the toolchain in the repository
Create rust-toolchain.toml at the repository root:
[toolchain]
channel = "1.99.1"
components = ["rustfmt", "clippy"]
profile = "minimal"
Use a full version such as 1.99.1, not stable. A bare stable floats, which defeats the purpose of pinning. Commit Cargo.lock alongside it for binaries and services.
Step 3: declare a minimum supported Rust version
In Cargo.toml:
[package]
name = "my-service"
version = "0.4.0"
edition = "2024"
rust-version = "1.85"
The rust-version is a promise to your users, not a pin for yourself. For a library, choose the oldest toolchain you actually test against. For an internal service that always builds with the pinned toolchain, keep rust-version close to the pin. Note that a 2024 edition crate cannot have an MSRV older than 1.85, because that is the release that stabilized the edition.
Test the MSRV in CI with a second job that installs exactly that version and runs cargo check.
Step 4: audit dependencies
cargo install cargo-audit --locked
cargo audit
cargo audit reads Cargo.lock and reports crates with RustSec advisories, with the advisory ID, title and the versions that fix it. For release binaries, consider building with cargo auditable build --release so the dependency list travels inside the binary and can be checked after deployment.
Step 5: set an update policy for CI toolchains
A simple policy that matches the six week train:
- Run a scheduled CI job against
betaevery week. It is allowed to fail, but someone reads the failures. - Within two weeks of a new stable release, open a pull request that moves
channelinrust-toolchain.tomlto the new version. - When a point release carries a security fix that affects you, move the pin the same day.
- Review
rust-versiononce per edition or once a year, whichever comes first.
A GitHub Actions job that honours the pinned file looks like this:
name: ci
on:
push:
pull_request:
schedule:
- cron: "0 6 * * 1"
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install pinned toolchain
run: rustup toolchain install
- name: Show toolchain
run: rustup show && rustc -vV
- name: Build and test
run: cargo test --locked
- name: Audit dependencies
run: |
cargo install cargo-audit --locked
cargo audit
beta:
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- run: rustup toolchain install beta --profile minimal
- run: cargo +beta test --locked
rustup toolchain install with no arguments reads rust-toolchain.toml, as described in the rustup 1.28.0 notes. The --locked flag stops Cargo from silently updating Cargo.lock in CI.
Step 6: verify installer integrity where it matters
For air gapped build hosts or base images where you install Rust without rustup, use the signed standalone installers:
VER=1.99.1
TARGET=x86_64-unknown-linux-gnu
BASE=https://static.rust-lang.org/dist
curl -sSfO "$BASE/rust-$VER-$TARGET.tar.xz"
curl -sSfO "$BASE/rust-$VER-$TARGET.tar.xz.asc"
curl -sSfO "$BASE/rust-$VER-$TARGET.tar.xz.sha256"
# Import the Rust signing key once, then check its fingerprint against keybase.io/rust
curl -sSf https://static.rust-lang.org/rust-key.gpg.ascii | gpg --import
gpg --verify "rust-$VER-$TARGET.tar.xz.asc" "rust-$VER-$TARGET.tar.xz"
sha256sum -c "rust-$VER-$TARGET.tar.xz.sha256"
Only extract and run the installer if both checks pass. For hosts that use rustup, you can at least check the rustup-init binary against its published .sha256 file before running it.
Step 7: subscribe to the right feeds
Subscribe to the Rust security announcements mailing list, watch the Rust blog, and make sure your dependency tooling pulls RustSec advisories. Toolchain advisories and crate advisories come from different sources, and you need both.
Common mistakes
Pinning an old stable for years. Teams pin 1.70 for stability and never move it. There is no LTS behind that pin. Every toolchain fix since then, including CVE-2023-38497, CVE-2024-24576 and the 2026 Cargo fixes, is missing. Pin, but move the pin on a schedule.
Confusing edition with version. "We are on Rust 2021" says nothing about which compiler you use. A 2021 edition crate can be built with 1.56 or 1.99.1. Security fixes come with compiler versions, not editions. Track both, separately.
Using nightly in production builds. Nightly is supported only until the next nightly. If you need an unstable feature, pin a dated nightly, document why, and plan the exit. Better still, check whether the feature has stabilized; many that once needed nightly, such as async and .await and const generics, are now stable.
Ignoring standard library advisories because the language is memory safe. Memory safety rules out many bugs, not all bugs. CVE-2024-24576 was an argument escaping problem, CVE-2022-21658 was a file system race, and the 2026 Cargo issues were about URL normalization and tar extraction. None of them are memory corruption, and all needed a toolchain update.
Treating cargo build as safe on untrusted code. The security policy is explicit that compiling a malicious project is not considered a vulnerability. Build scripts and procedural macros run with your user's permissions. Build untrusted code in a disposable, isolated environment.
Forgetting vendored C code. Rust binaries can carry musl, OpenSSL (through openssl-src and similar crates) or libssh2. Toolchain updates patch the copies the toolchain ships; crate updates patch the copies inside your dependencies. Inventory both.
Assuming rustup verifies signatures. It does not yet, according to its own documentation. If your threat model needs signature checks, use the signed standalone installers or mirror and verify toolchains yourself.
Letting stable float in rust-toolchain.toml. It looks pinned but it is not. Two builds a week apart can use different compilers.
FAQ
When was Rust 1.0 released?
Rust 1.0.0 was released on 15 May 2015. Rust 1.1 beta was released the same day, which started the six week release train that has run ever since.
Who created Rust?
Rust began as Graydon Hoare's project, with its earliest commits around 2006, and became a Mozilla Research project around 2010, according to the Rust core team's 2020 account. It has been governed by its own teams since 1.0 and is supported today by the independent Rust Foundation.
How often is Rust released?
A new stable minor version ships every six weeks, normally on a Thursday, with point releases when needed. Beta and nightly builds are produced daily.
Does Rust have an LTS release?
No. The Rust security policy says the project supports only the most recent stable release and the latest beta and nightly. Some Linux distributions and vendors maintain older Rust packages, but that support comes from them, not the Rust project.
What is the difference between a Rust edition and a Rust version?
A version, such as 1.99.1, is a specific compiler and toolchain release. An edition, such as 2024, is a set of opt in language rules that a crate selects in Cargo.toml. Any recent compiler supports every edition, and crates of different editions work together in one build.
When was the Rust 2024 edition released?
The 2024 edition was stabilized in Rust 1.85.0, released on 20 February 2025. The earlier editions were 2018 (Rust 1.31.0, 6 December 2018) and 2021 (Rust 1.56.0, 21 October 2021).
What is rust-toolchain.toml used for?
It pins the toolchain rustup uses inside a project directory: the channel or exact version, plus optional components, targets and profile. Commit it to source control so every developer and CI job uses the same compiler.
What does rust-version in Cargo.toml do?
It declares your crate's minimum supported Rust version. Since Rust 1.56, Cargo refuses to build the crate on an older toolchain unless the user passes --ignore-rust-version, and since the 2024 edition Cargo's resolver takes it into account by default when choosing dependency versions.
How do I report a security vulnerability in Rust?
Email security@rust-lang.org, as the Rust security policy describes. Vulnerabilities in third party crates go to the crate's maintainers and can be recorded in the RustSec Advisory Database.
Does rustup verify signatures when it downloads Rust?
Not yet. The rustup book says it downloads everything over HTTPS but does not yet validate signatures. Standalone installers come with GPG signatures if you need that check.
Where Safeguard fits, and where it does not
Most of this post is about the Rust toolchain itself, and Safeguard does not replace rustup, the Rust security announcements or your toolchain update policy. Where it helps is the other half of the picture: the crates in your Cargo.lock and the components inside the container images you ship. Safeguard's software composition analysis covers Cargo alongside other ecosystems, so a Rust service shows up in the same inventory and vulnerability view as the rest of your estate, and you can see which projects carry a given crate version when an advisory lands.
A new compiler every six weeks also means new builds, new lockfiles and new images, and every one of them pulls open source components again. Keeping those dependencies on fixed versions is the part of Rust security that does not come from the Rust project.
Fix it without waiting for upstream
Whatever the vulnerability, most of the risk sits in two gaps. The first is the time between a fix being published and that fix actually running in your production builds. The second, and worse, is the time before any fix exists at all, while a maintainer works out a patch and a release schedule. Waiting through both gaps is a habit, not a requirement. Safeguard gives teams three ways to close them.
1. Autonomous remediation: pull requests, not tickets
When a fixed version exists, Safeguard's Griffin models open a tested, policy gated pull request that moves the affected dependency to the safe version. You can run it on one repository or in bulk across every project that carries the vulnerable version. Remediation categories include dependencies, licenses, security posture and findings, and each one is set separately. Reachability analysis ranks the vulnerable code paths your application actually calls first, so the first pull requests you merge are the ones that matter most. Autonomous remediation ships switched off, with every category set to Manual, so your team decides how much runs on its own and what still needs a human approval.
2. Gold Open Source: the safe version in seconds, free
gold.safeguard.sh is free and needs no login. Search any CVE or package to see affected and fixed versions, CVSS, EPSS, CISA KEV status and a recommended safe version, or use the "Am I affected?" checker. The same data is available through a free read API, README status badges and RSS threat feeds.
3. Gold Registry: start from components that are already fixed
Gold Registry provides hardened, drop in replacements for upstream packages and container images. Every Gold artifact is held continuously to zero exploitable critical or high CVEs and a completed license check, with signed build provenance (signed with Safeguard's key and verifiable with cosign, SLSA Build Level 3 as the design target) and a public evidence page you can hand to an auditor. An artifact loses its Gold badge if it regresses. Teams can point their own package directory at the registry so hardened equivalents resolve without changing how developers install anything.
When upstream has no fix yet, or will not ship one, Safeguard first works to get the fix accepted upstream. If the issue is severe or upstream will not move, Safeguard builds a fork, fixes the vulnerability there and publishes a hardened Gold build, so you are not stuck on a maintainer's release schedule. You can also request a hardened, compatibility tested build of a specific package. Ask which packages it covers before you plan around it.
| Your situation | What to use |
|---|---|
| A fixed version exists | Autonomous remediation opens the upgrade pull request; Gold Open Source confirms the safe version |
| You need to know today whether you are affected | Gold Open Source lookup and "Am I affected?" checker, free and without login |
| You want vulnerable versions to stop shipping | Safeguard policies and gates in CI |
| Upstream has no fix yet, or will not ship one | A custom Gold request; fork and patch |
| You want to start clean on new projects | Pull hardened components and images from Gold Registry |
One honest limit: when the vulnerable code lives in a vendor appliance, a hosted service or an operating system runtime you do not build yourself, the fix still has to come from that vendor or distribution. The steps above apply to the open source dependencies and container images you build and ship, which is where most teams carry the largest and least tracked share of their exposure.
See how Safeguard would help
The first demo is a real Safeguard CLI session. It asks the assistant to fix a lodash CVE in a JavaScript repository: the CLI reads the finding and advisory, asks before any command that changes something, edits the manifest, runs the install and tests with your approval and pushes nothing. The same flow applies to a Rust repository, where the change is a crate version in Cargo.toml followed by cargo update -p for that crate and cargo test.
Click through it at your own pace, or open it full screen.
The second demo sets up the Safeguard runner on your own machine, approves it with a device code and then scans from the terminal. For Rust teams that pin a toolchain per repository, running the scan locally means it runs against the same checkout and lockfile your developers build.
Click through it at your own pace, or open it full screen.
The third demo connects Claude to the Safeguard MCP server with OAuth and shows how to choose which tools Claude can use. It is a way to ask questions such as which projects still carry a crate version named in a RustSec advisory, from inside a chat.
Click through it at your own pace, or open it full screen.
To try it on your own code, download Safeguard or read the CLI documentation.
Quick check
If your project sets edition = "2021", which compiler fixes does it get?
Whatever fixes are in the compiler you build with. Editions select language rules, not compiler versions. A 2021 edition crate built with Rust 1.99.1 gets every fix in 1.99.1; built with 1.60 it gets none of the later ones.
Your CI pins Rust 1.80 and a new standard library CVE is announced. Will the Rust project ship a 1.80 point release?
No. The Rust security policy supports only the most recent stable release, plus the latest beta and nightly. The fix ships in the current stable line, so the supported path is to move your pin forward.
Sources
- Announcing Rust 1.0 (Rust blog, 15 May 2015)
- Rust RELEASES.md (rust-lang/rust)
- Rust Forge: release process
- Rust Forge: other installation methods
- The Rust Programming Language: how Rust is made and nightly Rust
- RFC 507: release channels
- RFC 2052: epochs (editions)
- The Rust Edition Guide: what are editions?
- The Rust Edition Guide: Rust 2024
- Announcing Rust 1.31 and Rust 2018
- Announcing Rust 1.39.0
- Announcing Rust 1.51.0
- Announcing Rust 1.56.0 and Rust 2021
- Announcing Rust 1.65.0
- Announcing Rust 1.85.0 and Rust 2024
- rustup book: channels
- rustup book: overrides and the toolchain file
- rustup book: security
- Announcing rustup 1.28.0
- Announcing rustup 1.28.1
- The Cargo Book: the rust-version field
- The Cargo Book: the manifest format
- Rust security policy
- Rust governance
- Laying the foundation for Rust's future (Rust blog, 18 August 2020)
- Six years of Rust (Rust blog, 15 May 2021)
- Launching the Rust Foundation Maintainers Fund (Rust blog, 2 June 2026)
- Introducing the Rust Leadership Council (Rust blog, 20 June 2023)
- RFC 3392: Leadership Council
- RFC 3691: trusted publishing for crates.io
- crates.io development update, July 2025
- Security advisory for the standard library (CVE-2021-42574)
- Security advisory for the standard library (CVE-2022-21658)
- Security advisory for Cargo (CVE-2022-46176)
- Security advisory for the standard library (CVE-2024-24576)
- Security advisory for the standard library (CVE-2024-43402)
- Security advisory for Cargo (CVE-2026-33056)
- Security advisory for Cargo (CVE-2026-5222)
- Security advisory for Cargo (CVE-2026-5223)
- Supply chain attack on arrayref (Rust blog, 20 August 2026)
- rust-lang/rust security advisories
- RustSec
- RustSec Advisory Database
Last reviewed: 25 October 2026. Rust ships every six weeks; check the Rust blog and RELEASES.md for the current stable version.