diff --git a/Cargo.lock b/Cargo.lock
index a6f8dbf5fc..586d2311ed 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -36,10 +36,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
 dependencies = [
  "cfg-if",
- "getrandom",
+ "getrandom 0.2.15",
  "once_cell",
  "version_check",
- "zerocopy",
+ "zerocopy 0.7.35",
 ]
 
 [[package]]
@@ -753,7 +753,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
 dependencies = [
  "cfg-if",
  "libc",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi 0.13.3+wasi-0.2.2",
+ "windows-targets 0.52.0",
 ]
 
 [[package]]
@@ -860,7 +872,7 @@ dependencies = [
  "idna",
  "ipnet",
  "once_cell",
- "rand",
+ "rand 0.8.5",
  "thiserror 1.0.69",
  "tinyvec",
  "tokio",
@@ -881,7 +893,7 @@ dependencies = [
  "lru-cache",
  "once_cell",
  "parking_lot",
- "rand",
+ "rand 0.8.5",
  "resolv-conf",
  "smallvec",
  "thiserror 1.0.69",
@@ -1261,7 +1273,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
 dependencies = [
  "cfg-if",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.0",
 ]
 
 [[package]]
@@ -1584,7 +1596,7 @@ dependencies = [
  "ahash",
  "linkerd-stack",
  "parking_lot",
- "rand",
+ "rand 0.9.0",
  "tokio",
  "tokio-test",
  "tower-test",
@@ -1653,7 +1665,7 @@ dependencies = [
  "futures",
  "pin-project",
  "quickcheck",
- "rand",
+ "rand 0.9.0",
  "thiserror 2.0.11",
  "tokio",
 ]
@@ -1820,7 +1832,7 @@ dependencies = [
  "http",
  "linkerd2-proxy-api",
  "maplit",
- "rand",
+ "rand 0.9.0",
  "regex",
  "thiserror 2.0.11",
  "tracing",
@@ -2088,7 +2100,7 @@ dependencies = [
  "parking_lot",
  "prometheus-client",
  "quickcheck",
- "rand",
+ "rand 0.9.0",
  "tokio",
  "tokio-test",
  "tower",
@@ -2131,7 +2143,7 @@ dependencies = [
  "linkerd-proxy-balance-queue",
  "linkerd-proxy-core",
  "linkerd-stack",
- "rand",
+ "rand 0.9.0",
  "tokio",
  "tower",
  "tracing",
@@ -2250,7 +2262,7 @@ dependencies = [
  "linkerd-tracing",
  "parking_lot",
  "pin-project",
- "rand",
+ "rand 0.9.0",
  "thiserror 2.0.11",
  "tokio",
  "tokio-test",
@@ -2355,7 +2367,7 @@ dependencies = [
  "pin-project",
  "prost-types",
  "quickcheck",
- "rand",
+ "rand 0.9.0",
  "thiserror 2.0.11",
  "tokio",
  "tonic",
@@ -2373,7 +2385,7 @@ dependencies = [
  "linkerd-proxy-balance",
  "linkerd-stack",
  "pin-project",
- "rand",
+ "rand 0.9.0",
  "tokio",
  "tower",
 ]
@@ -2551,7 +2563,7 @@ dependencies = [
  "linkerd-dns",
  "linkerd-tls",
  "linkerd2-proxy-api",
- "rand",
+ "rand 0.9.0",
  "regex",
  "thiserror 2.0.11",
  "tracing",
@@ -2603,7 +2615,7 @@ dependencies = [
  "http",
  "linkerd-error",
  "linkerd-stack",
- "rand",
+ "rand 0.8.5",
  "thiserror 1.0.69",
  "tower",
  "tracing",
@@ -2805,7 +2817,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
 dependencies = [
  "libc",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
  "windows-sys 0.52.0",
 ]
 
@@ -2984,7 +2996,7 @@ dependencies = [
  "futures-util",
  "opentelemetry",
  "percent-encoding",
- "rand",
+ "rand 0.8.5",
  "thiserror 1.0.69",
 ]
 
@@ -3118,7 +3130,7 @@ version = "0.2.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
 dependencies = [
- "zerocopy",
+ "zerocopy 0.7.35",
 ]
 
 [[package]]
@@ -3250,7 +3262,7 @@ version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
 dependencies = [
- "rand",
+ "rand 0.8.5",
 ]
 
 [[package]]
@@ -3269,8 +3281,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
 dependencies = [
  "libc",
- "rand_chacha",
- "rand_core",
+ "rand_chacha 0.3.1",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
+dependencies = [
+ "rand_chacha 0.9.0",
+ "rand_core 0.9.0",
+ "zerocopy 0.8.14",
 ]
 
 [[package]]
@@ -3280,7 +3303,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
 dependencies = [
  "ppv-lite86",
- "rand_core",
+ "rand_core 0.6.4",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.9.0",
 ]
 
 [[package]]
@@ -3289,7 +3322,17 @@ version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
 dependencies = [
- "getrandom",
+ "getrandom 0.2.15",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b08f3c9802962f7e1b25113931d94f43ed9725bebc59db9d0c3e9a23b67e15ff"
+dependencies = [
+ "getrandom 0.3.1",
+ "zerocopy 0.8.14",
 ]
 
 [[package]]
@@ -3382,7 +3425,7 @@ checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d"
 dependencies = [
  "cc",
  "cfg-if",
- "getrandom",
+ "getrandom 0.2.15",
  "libc",
  "spin",
  "untrusted",
@@ -3689,7 +3732,7 @@ checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704"
 dependencies = [
  "cfg-if",
  "fastrand",
- "getrandom",
+ "getrandom 0.2.15",
  "once_cell",
  "rustix",
  "windows-sys 0.52.0",
@@ -3980,7 +4023,7 @@ dependencies = [
  "indexmap 1.9.3",
  "pin-project",
  "pin-project-lite",
- "rand",
+ "rand 0.8.5",
  "slab",
  "tokio",
  "tokio-util",
@@ -4171,6 +4214,15 @@ version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
+[[package]]
+name = "wasi"
+version = "0.13.3+wasi-0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
+dependencies = [
+ "wit-bindgen-rt",
+]
+
 [[package]]
 name = "wasm-bindgen"
 version = "0.2.93"
@@ -4396,6 +4448,15 @@ dependencies = [
  "windows-sys 0.48.0",
 ]
 
+[[package]]
+name = "wit-bindgen-rt"
+version = "0.33.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
+dependencies = [
+ "bitflags 2.4.2",
+]
+
 [[package]]
 name = "write16"
 version = "1.0.0"
@@ -4465,7 +4526,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
 dependencies = [
  "byteorder",
- "zerocopy-derive",
+ "zerocopy-derive 0.7.35",
+]
+
+[[package]]
+name = "zerocopy"
+version = "0.8.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a367f292d93d4eab890745e75a778da40909cab4d6ff8173693812f79c4a2468"
+dependencies = [
+ "zerocopy-derive 0.8.14",
 ]
 
 [[package]]
@@ -4479,6 +4549,17 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "zerocopy-derive"
+version = "0.8.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3931cb58c62c13adec22e38686b559c86a30565e16ad6e8510a337cedc611e1"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "zerofrom"
 version = "0.1.5"
diff --git a/deny.toml b/deny.toml
index 5c1f1e5920..fa84802a02 100644
--- a/deny.toml
+++ b/deny.toml
@@ -62,10 +62,13 @@ skip = [
     # Some dependencies still use indexmap v1.
     { name = "indexmap", version = "1" },
     { name = "hashbrown", version = "0.12" },
+
 ]
 skip-tree = [
     # thiserror v2 is still propagating through the ecosystem
     { name = "thiserror", version = "1" },
+    # rand 0.9 is still propagating through the ecosystem
+    { name = "rand", version = "0.8" },
 ]
 
 [sources]
diff --git a/linkerd/distribute/Cargo.toml b/linkerd/distribute/Cargo.toml
index d99437bc21..3bd193d3dc 100644
--- a/linkerd/distribute/Cargo.toml
+++ b/linkerd/distribute/Cargo.toml
@@ -9,7 +9,7 @@ publish = false
 ahash = "0.8"
 linkerd-stack = { path = "../stack" }
 parking_lot = "0.12"
-rand = { version = "0.8", features = ["small_rng"] }
+rand = { version = "0.9", features = ["small_rng"] }
 tokio = { version = "1", features = ["macros"] }
 tracing = "0.1"
 
diff --git a/linkerd/distribute/src/keys.rs b/linkerd/distribute/src/keys.rs
index 3ad75275ee..439ff3839e 100644
--- a/linkerd/distribute/src/keys.rs
+++ b/linkerd/distribute/src/keys.rs
@@ -1,6 +1,6 @@
 use ahash::{HashMap, HashMapExt};
 use rand::{
-    distributions::{WeightedError, WeightedIndex},
+    distr::weighted::{Error as WeightedError, WeightedIndex},
     prelude::Distribution as _,
     Rng,
 };
diff --git a/linkerd/distribute/src/params.rs b/linkerd/distribute/src/params.rs
index b27728983f..9d7b57e35d 100644
--- a/linkerd/distribute/src/params.rs
+++ b/linkerd/distribute/src/params.rs
@@ -3,7 +3,6 @@ use crate::{
     WeightedServiceKeys,
 };
 use ahash::AHashSet;
-use rand::distributions::WeightedError;
 use std::{fmt::Debug, hash::Hash, sync::Arc};
 
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -73,7 +72,7 @@ impl<K> Distribution<K> {
 
     pub fn random_available<T: IntoIterator<Item = (K, u32)>>(
         iter: T,
-    ) -> Result<Self, WeightedError> {
+    ) -> Result<Self, rand::distr::weighted::Error> {
         let weighted_keys = WeightedServiceKeys::new(
             iter.into_iter()
                 .map(|(key, weight)| WeightedKey { key, weight }),
diff --git a/linkerd/distribute/src/service/random.rs b/linkerd/distribute/src/service/random.rs
index 028d0a5a0d..a0b916a041 100644
--- a/linkerd/distribute/src/service/random.rs
+++ b/linkerd/distribute/src/service/random.rs
@@ -1,7 +1,7 @@
 use crate::{keys::KeyId, WeightedServiceKeys};
 use ahash::HashMap;
 use linkerd_stack::{NewService, Service};
-use rand::{distributions::WeightedError, rngs::SmallRng, SeedableRng};
+use rand::{distr::weighted, rngs::SmallRng, SeedableRng};
 use std::{
     hash::Hash,
     sync::Arc,
@@ -21,7 +21,7 @@ pub(crate) struct RandomAvailableSelection<K, S> {
 }
 
 fn new_rng() -> SmallRng {
-    SmallRng::from_rng(rand::thread_rng()).expect("RNG must initialize")
+    SmallRng::from_rng(&mut rand::rng())
 }
 
 impl<K, S> RandomAvailableSelection<K, S> {
@@ -92,7 +92,7 @@ where
             // to `poll_ready` can try this backend again.
             match selector.disable_backend(id) {
                 Ok(()) => {}
-                Err(WeightedError::AllWeightsZero) => {
+                Err(weighted::Error::InsufficientNonZero) => {
                     // There are no backends remaining.
                     break;
                 }
diff --git a/linkerd/exp-backoff/Cargo.toml b/linkerd/exp-backoff/Cargo.toml
index b550abef73..430976eb35 100644
--- a/linkerd/exp-backoff/Cargo.toml
+++ b/linkerd/exp-backoff/Cargo.toml
@@ -8,7 +8,7 @@ publish = false
 
 [dependencies]
 futures = { version = "0.3", default-features = false }
-rand = { version = "0.8", features = ["small_rng"] }
+rand = { version = "0.9", features = ["small_rng"] }
 thiserror = "2"
 tokio = { version = "1", features = ["time"] }
 pin-project = "1"
diff --git a/linkerd/exp-backoff/src/lib.rs b/linkerd/exp-backoff/src/lib.rs
index 45ee8ff465..08ea9d26d3 100644
--- a/linkerd/exp-backoff/src/lib.rs
+++ b/linkerd/exp-backoff/src/lib.rs
@@ -3,7 +3,7 @@
 
 use futures::Stream;
 use pin_project::pin_project;
-use rand::{rngs::SmallRng, thread_rng, SeedableRng};
+use rand::{rngs::SmallRng, SeedableRng};
 use std::future::Future;
 use std::pin::Pin;
 use std::task::{Context, Poll};
@@ -74,7 +74,7 @@ impl ExponentialBackoff {
     pub fn stream(&self) -> ExponentialBackoffStream {
         ExponentialBackoffStream {
             backoff: *self,
-            rng: SmallRng::from_rng(&mut thread_rng()).expect("RNG must be valid"),
+            rng: SmallRng::from_rng(&mut rand::rng()),
             iterations: 0,
             sleeping: false,
             sleep: Box::pin(time::sleep(time::Duration::from_secs(0))),
@@ -103,7 +103,7 @@ impl ExponentialBackoff {
         if self.jitter == 0.0 {
             time::Duration::default()
         } else {
-            let jitter_factor = rng.gen::<f64>();
+            let jitter_factor = rng.random::<f64>();
             debug_assert!(
                 jitter_factor > 0.0,
                 "rng returns values between 0.0 and 1.0"
@@ -212,7 +212,7 @@ mod tests {
                 Ok(backoff) => backoff,
             };
 
-            let j = backoff.jitter(base, &mut rand::thread_rng());
+            let j = backoff.jitter(base, &mut rand::rng());
             if jitter == 0.0 || base_ms == 0 || max_ms == base_ms {
                 TestResult::from_bool(j == time::Duration::default())
             } else {
diff --git a/linkerd/http/route/Cargo.toml b/linkerd/http/route/Cargo.toml
index e244604c3a..def0770f30 100644
--- a/linkerd/http/route/Cargo.toml
+++ b/linkerd/http/route/Cargo.toml
@@ -11,7 +11,7 @@ proto = ["linkerd2-proxy-api"]
 [dependencies]
 http = { workspace = true }
 regex = "1"
-rand = "0.8"
+rand = "0.9"
 thiserror = "2"
 tracing = "0.1"
 url = "2"
diff --git a/linkerd/http/route/src/http/filter/inject_failure.rs b/linkerd/http/route/src/http/filter/inject_failure.rs
index 47fe440dc4..6df7579847 100644
--- a/linkerd/http/route/src/http/filter/inject_failure.rs
+++ b/linkerd/http/route/src/http/filter/inject_failure.rs
@@ -19,16 +19,16 @@ pub struct FailureResponse {
 pub struct Distribution {
     numerator: u32,
     denominator: u32,
-    inner: rand::distributions::Bernoulli,
+    inner: rand::distr::Bernoulli,
 }
 
 // === impl InjectFailure ===
 
 impl<T: Clone> InjectFailure<T> {
     pub fn apply(&self) -> Option<T> {
-        use rand::distributions::Distribution;
+        use rand::distr::Distribution;
 
-        if self.distribution.sample(&mut rand::thread_rng()) {
+        if self.distribution.sample(&mut rand::rng()) {
             return Some(self.response.clone());
         }
 
@@ -43,8 +43,8 @@ impl Distribution {
     pub fn from_ratio(
         numerator: u32,
         denominator: u32,
-    ) -> Result<Self, rand::distributions::BernoulliError> {
-        let inner = rand::distributions::Bernoulli::from_ratio(numerator, denominator)?;
+    ) -> Result<Self, rand::distr::BernoulliError> {
+        let inner = rand::distr::Bernoulli::from_ratio(numerator, denominator)?;
         Ok(Self {
             numerator,
             denominator,
@@ -59,7 +59,7 @@ impl Default for Distribution {
     }
 }
 
-impl rand::distributions::Distribution<bool> for Distribution {
+impl rand::distr::Distribution<bool> for Distribution {
     #[inline]
     fn sample<R: rand::Rng + ?Sized>(&self, rng: &mut R) -> bool {
         self.inner.sample(rng)
@@ -100,7 +100,7 @@ pub mod proto {
 
     #[derive(Debug, thiserror::Error)]
     #[error("invalid request distribution: {0}")]
-    pub struct InvalidDistribution(#[from] rand::distributions::BernoulliError);
+    pub struct InvalidDistribution(#[from] rand::distr::BernoulliError);
 
     // === impl InjectFailure ===
 
diff --git a/linkerd/pool/p2c/Cargo.toml b/linkerd/pool/p2c/Cargo.toml
index a2fda5e4cd..9caf1a04e4 100644
--- a/linkerd/pool/p2c/Cargo.toml
+++ b/linkerd/pool/p2c/Cargo.toml
@@ -11,7 +11,7 @@ ahash = "0.8"
 futures = { version = "0.3", default-features = false }
 indexmap = "2"
 prometheus-client = "0.22"
-rand = { version = "0.8", features = ["small_rng"] }
+rand = { version = "0.9", features = ["small_rng"] }
 tokio = { version = "1", features = ["rt", "sync", "time"] }
 tracing = "0.1"
 
diff --git a/linkerd/pool/p2c/src/lib.rs b/linkerd/pool/p2c/src/lib.rs
index 29c61f1cd2..b466058b11 100644
--- a/linkerd/pool/p2c/src/lib.rs
+++ b/linkerd/pool/p2c/src/lib.rs
@@ -11,7 +11,7 @@ use linkerd_error::Error;
 use linkerd_metrics::prom;
 use linkerd_pool::Pool;
 use linkerd_stack::{NewService, Service};
-use rand::{rngs::SmallRng, thread_rng, Rng, SeedableRng};
+use rand::{rngs::SmallRng, Rng, SeedableRng};
 use std::{
     collections::hash_map::Entry,
     net::SocketAddr,
@@ -76,7 +76,7 @@ where
     S::Metric: std::fmt::Debug,
 {
     pub fn new(metrics: P2cMetrics, new_endpoint: N) -> Self {
-        let rng = SmallRng::from_rng(&mut thread_rng()).expect("RNG must be seeded");
+        let rng = SmallRng::from_rng(&mut rand::rng());
         Self {
             rng,
             metrics,
@@ -120,8 +120,8 @@ fn gen_pair(rng: &mut SmallRng, len: usize) -> (usize, usize) {
     debug_assert!(len >= 2, "must have at least two endpoints");
     // Get two distinct random indexes (in a random order) and
     // compare the loads of the service at each index.
-    let aidx = rng.gen_range(0..len);
-    let mut bidx = rng.gen_range(0..(len - 1));
+    let aidx = rng.random_range(0..len);
+    let mut bidx = rng.random_range(0..(len - 1));
     if bidx >= aidx {
         bidx += 1;
     }
@@ -376,7 +376,7 @@ mod tests {
             if len < 2 {
                 return quickcheck::TestResult::discard();
             }
-            let mut rng = SmallRng::from_rng(rand::thread_rng()).expect("rng");
+            let mut rng = SmallRng::from_rng(&mut rand::rng());
             let (aidx, bidx) = gen_pair(&mut rng, len);
             quickcheck::TestResult::from_bool(aidx != bidx)
         }
diff --git a/linkerd/proxy/balance/Cargo.toml b/linkerd/proxy/balance/Cargo.toml
index 86fa263763..c1cc5c3c50 100644
--- a/linkerd/proxy/balance/Cargo.toml
+++ b/linkerd/proxy/balance/Cargo.toml
@@ -7,7 +7,7 @@ publish = false
 
 [dependencies]
 futures = { version = "0.3", default-features = false }
-rand = "0.8"
+rand = "0.9"
 tokio = { version = "1", features = ["time"] }
 tracing = "0.1"
 
diff --git a/linkerd/proxy/http/Cargo.toml b/linkerd/proxy/http/Cargo.toml
index cba320704a..df9adc6570 100644
--- a/linkerd/proxy/http/Cargo.toml
+++ b/linkerd/proxy/http/Cargo.toml
@@ -33,7 +33,7 @@ hyper = { workspace = true, features = [
 hyper-balance = { path = "../../../hyper-balance" }
 parking_lot = "0.12"
 pin-project = "1"
-rand = "0.8"
+rand = "0.9"
 thiserror = "2"
 tokio = { version = "1", features = ["rt", "sync", "time"] }
 tower = { version = "0.4", default-features = false }
diff --git a/linkerd/proxy/tap/Cargo.toml b/linkerd/proxy/tap/Cargo.toml
index 811a4f7d71..b7ee18b1cb 100644
--- a/linkerd/proxy/tap/Cargo.toml
+++ b/linkerd/proxy/tap/Cargo.toml
@@ -23,7 +23,7 @@ linkerd-stack = { path = "../../stack" }
 linkerd-tls = { path = "../../tls" }
 parking_lot = "0.12"
 prost-types = { workspace = true }
-rand = { version = "0.8" }
+rand = { version = "0.9" }
 thiserror = "2"
 tokio = { version = "1", features = ["time"] }
 tower = { version = "0.4", default-features = false }
diff --git a/linkerd/proxy/tcp/Cargo.toml b/linkerd/proxy/tcp/Cargo.toml
index 3d7107eee8..5a83cab74e 100644
--- a/linkerd/proxy/tcp/Cargo.toml
+++ b/linkerd/proxy/tcp/Cargo.toml
@@ -13,7 +13,7 @@ linkerd-duplex = { path = "../../duplex" }
 linkerd-error = { path = "../../error" }
 linkerd-proxy-balance = { path = "../../proxy/balance" }
 linkerd-stack = { path = "../../stack" }
-rand = "0.8"
+rand = "0.9"
 tokio = { version = "1" }
 tower = { version = "0.4.13", default-features = false }
 pin-project = "1"
diff --git a/linkerd/tls/route/Cargo.toml b/linkerd/tls/route/Cargo.toml
index b8915ffc72..75df99dc18 100644
--- a/linkerd/tls/route/Cargo.toml
+++ b/linkerd/tls/route/Cargo.toml
@@ -10,7 +10,7 @@ proto = ["linkerd2-proxy-api"]
 
 [dependencies]
 regex = "1"
-rand = "0.8"
+rand = "0.9"
 thiserror = "2"
 tracing = "0.1"
 linkerd-tls = { path = "../" }