Join our Newsletter — 33% off our NHI Course
Home› Guides› Memory-Safe Languages Guide: Why They Matter and How…
Guide Application Security

Memory-Safe Languages Guide: Why They Matter and How to Migrate

PDF for newsletter subscribers · free to read online

← All guides
By Lalit Choda, NHI Mgmt Group Updated 24 October 2026 14 min read
On this page

Memory safety bugs in C and C++ code have been the largest single class of serious vulnerabilities in widely used software for well over a decade, and no amount of code review or testing has made them go away. Out-of-bounds writes, use-after-free and out-of-bounds reads still rank in the top ten of the 2025 CWE Top 25, and they are the bugs behind many exploited zero-days and memory leaks of credentials. Memory-safe languages remove most of these bugs by construction, and government agencies in the Five Eyes now ask software manufacturers to publish roadmaps for adopting them. This guide explains what memory safety means, the evidence for it, how to choose a language, how to plan and run a migration without rewriting everything, how to harden the C and C++ that remains, and how to measure progress. It is for application security leads, engineering managers and architects who own native code. General secure development practice is covered in the Secure Coding Guide.

Key takeaways

  • The problem is concentrated and measurable: Microsoft, Chromium and Android have each reported memory safety issues as roughly 70 percent of their serious vulnerabilities before adopting safer approaches.
  • New code matters most: vulnerabilities cluster in new and recently changed code, so writing new code in a memory-safe language cuts risk long before old code is replaced.
  • A roadmap is the expected deliverable: CISA, NSA and partner agencies ask manufacturers for dated phases, a cut-off date for new code in memory-unsafe languages, and a plan for dependencies.
  • Interoperability is the migration strategy: NSA and CISA state that adoption does not require a complete rewrite; safe components are introduced behind interfaces into existing C and C++.
  • Remaining C and C++ still needs hardening: standard library hardening, compiler flags, sanitisers, fuzzing and hardened allocators reduce exploitability where migration is not yet feasible.

What memory safety means

A language is memory safe when the language and its runtime prevent a program from reading or writing memory it does not own, in code that does not explicitly opt out. The NSA and CISA information sheet of June 2025 describes the built-in protections as bounds checking, memory management and data race prevention, embedded at language level so that memory safety issues are prevented from the outset.

Bug classCWE (2025 Top 25 rank)What happensHow memory-safe languages prevent it
Out-of-bounds writeCWE-787 (5)Writes past a buffer, corrupting adjacent data or control flowBounds-checked indexing and slices
Use after freeCWE-416 (7)Memory reused after release, often attacker-controlledGarbage collection, reference counting, or compile-time ownership and lifetimes
Out-of-bounds readCWE-125 (8)Leaks adjacent memory: keys, tokens, passwordsBounds checks; no reading of uninitialised buffers in safe code
Classic buffer overflowCWE-120 (11)Copy without checking input sizeLength-carrying strings and slices
NULL pointer dereferenceCWE-476 (13)Crash, sometimes exploitableOption or nullable types checked at compile time (Rust, Swift, Kotlin)
Stack and heap overflowsCWE-121 (14), CWE-122 (16)Overflow of stack or heap buffersBounds checking

Memory safety does not remove logic flaws, injection, authorisation errors or misuse of cryptography. It removes one large class, which frees review and testing effort for the rest. See the CWE Top 25 Guide.

The evidence

  • Microsoft: about 70 percent of Microsoft CVEs (2006 to 2018 data) were memory safety vulnerabilities, as cited in The Case for Memory Safe Roadmaps.
  • Chromium: the Chromium security team reports that around 70 percent of its serious security bugs are memory safety problems, based on 912 high or critical bugs affecting Stable since 2015, and that half of those are use-after-free.
  • Mozilla and zero-days: the same agency guide cites 32 of 34 critical or high Mozilla bugs in one analysis, and Google Project Zero's finding that 67 percent of 2021 in-the-wild zero-days were memory safety vulnerabilities.
  • Android: Google reported memory safety vulnerabilities falling from 76 percent of Android vulnerabilities in 2019 to 35 percent in 2022 as new code moved to memory-safe languages, and in November 2025 reported them below 20 percent for the first time.
  • Defect density and delivery speed: in the same 2025 post Google estimates about 0.2 vulnerabilities per million lines of Rust against close to 1,000 per million lines for historical C and C++ in Android, with a rollback rate about four times lower for medium and large Rust changes and about 25 percent less time in code review.

The Android result is the key planning insight: the vulnerability share fell mainly because new code was written in memory-safe languages, not because old code was rewritten.

Choosing a memory-safe language

The Case for Memory Safe Roadmaps lists C#, Go, Java, Python, Rust and Swift as examples of memory-safe languages. Chromium's memory safety page also names Java, Kotlin, JavaScript, Rust and Swift as options where applicable. The choice is driven mainly by where the code runs and what it must interoperate with.

LanguageMemory managementGood fitTrade-offs
RustCompile-time ownership and borrowing, no garbage collectorSystems code, parsers, codecs, kernels and drivers, embedded, performance-critical libraries replacing C or C++Learning curve; unsafe blocks and FFI need review
GoGarbage collectedNetwork services, infrastructure tooling, CLIsGC pauses and runtime size; data races must be tested for with the race detector
Java and KotlinGarbage collected (JVM)Enterprise services, Android appsJVM footprint; JNI native code is outside the safety boundary
C#Garbage collected (.NET)Enterprise and Windows services, toolingunsafe contexts and P/Invoke bypass checks
SwiftAutomatic reference countingApple platform apps and servicesInterop with C and Objective-C needs care
PythonGarbage collected, interpretedAutomation, data, glue codePerformance; native extension modules are often C
  • Replacing C or C++ in place: where no garbage collector is acceptable (kernels, firmware, real-time paths, libraries loaded into other processes), Rust is the usual candidate.
  • New services: a managed language the team already knows usually gives most of the safety benefit at the lowest cost.
  • Small teams: standardise on one memory-safe language per domain rather than several, so review skills and tooling stay concentrated.
  • Large estates: set the language choice by component type in an architecture standard, and fund a central team to own interop libraries and build tooling.

The unsafe boundary

Every memory-safe language has escape hatches: Rust unsafe, C# unsafe and P/Invoke, Java JNI, Python C extensions, and any foreign function interface into C. Safety claims hold only for code that stays inside the safe subset, so the boundary has to be governed.

  • What Rust unsafe allows: the Rust book lists five abilities: dereference a raw pointer, call an unsafe function or method, access or modify a mutable static, implement an unsafe trait, and access union fields. The borrow checker and other checks remain active inside unsafe blocks.
  • Keep it small and wrapped: the book's advice is to keep unsafe blocks small and wrap them in safe abstractions whose preconditions are checked, as the standard library does.
  • Review policy: require a written safety comment and a second reviewer with Rust experience for any new unsafe block; flag it in CI and report counts per crate.
  • Test unsafe code with Miri: cargo miri test detects out-of-bounds access, use-after-free, use of uninitialised data, misaligned access, invalid values and data races in the executions it runs. It cannot run most FFI or networking, and it shows the presence of undefined behaviour, not proof of soundness.
  • Treat the FFI boundary as an attack surface: validate lengths and ownership at every crossing; prefer generated bindings over hand-written declarations.
  • Dependencies count: a memory-safe application can still link memory-unsafe C libraries (compression, image, TLS). The agencies' roadmap guidance asks for an explicit external dependency plan for C and C++ libraries, including open source.

Building a memory safe roadmap

The Case for Memory Safe Roadmaps (December 2023), issued by CISA, NSA, FBI, the Australian Signals Directorate's ACSC, the Canadian Centre for Cyber Security, the UK NCSC, New Zealand's NCSC and CERT NZ, asks manufacturers to publish a roadmap owned by a senior executive. Its recommended elements map directly to a programme plan.

Roadmap element (agency guidance)What to decideExample evidence
Defined phases with dates and outcomesLanguage evaluation, pilots, threat modelling, refactoring wavesPublished plan with dated milestones
Date for new code in memory-safe languagesThe cut-off after which new code is written only in a memory-safe language, and the exception processEngineering standard, CI rule on new native files
Internal developer trainingWho is trained, when, and how support is providedTraining records, internal guilds
External dependency planHow C and C++ libraries, including open source, are replaced, sandboxed or hardenedDependency inventory flagged by language
Transparency planHow often progress is reported (for example quarterly or semi-annually)Public or customer-facing updates
CVE support planSupplying CWE data for all CVEs in a timely wayCVE records with CWE fields completed

For prioritisation, the guidance suggests starting with new and smaller projects, replacing self-contained components, and focusing first on security-critical code. In practice that means code that parses untrusted input (network protocols, file formats, media codecs, decompression), runs with high privilege, or sits on an internet-facing path. Use your threat model to rank components. See the Threat Modelling Guide.

How to migrate in practice

  1. Inventory native code: lines of C and C++ by component, owner, exposure to untrusted input and privilege, plus native dependencies. Your SBOM can flag components by language; see the SBOM Guide.
  2. Set the policy for new code: new components in a memory-safe language from a published date; new C or C++ files require an approved exception.
  3. Pilot one self-contained component: a parser or codec with a clean interface and good tests. Build the toolchain, CI, interop bindings and release process once, and measure performance and defect rates.
  4. Run old and new side by side: ship the new implementation behind a flag or selectable backend, compare outputs with differential testing and fuzzing, and keep the C or C++ version as the rollback path until the new one has run in production.
  5. Expand by priority: move high-exposure components in waves; for each wave, decide replace, isolate (separate process or sandbox) or harden.
  6. Retire the old code: remove the legacy implementation once the replacement has met its quality bar, so you do not maintain two attack surfaces.
  7. Report progress: publish roadmap updates on the cadence you committed to.

The Android experience shows why step 2 comes early: because vulnerabilities concentrate in new code, stopping the inflow of new memory-unsafe code delivers measurable results before large rewrites start.

Hardening the C and C++ that remains

NSA and CISA note that where memory-safe languages are not feasible, non-memory-safe code can still be made safer. These measures reduce risk; they do not make C or C++ memory safe.

MeasureSpecific setting or toolEffect
Standard library hardening (libc++)-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FASTBounds and valid-range checks on containers and iterators; recommended for production; no ABI change
Standard library hardening (libstdc++)-D_GLIBCXX_ASSERTIONSPrecondition checks on library calls
Fortify-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 with -O2Compile and run-time checks on unsafe libc calls
Stack protection-fstack-protector-strong, -fstack-clash-protectionCanaries and stack guard probing
Control-flow protection-fcf-protection=full (x86_64), -mbranch-protection=standard (AArch64)Hardware-assisted defence against ROP and JOP
Initialisation-ftrivial-auto-var-init=zeroRemoves uninitialised stack variable leaks
Linker hardening-Wl,-z,relro -Wl,-z,now, -Wl,-z,noexecstack, -fPIE -pieRead-only relocations, non-executable stack, ASLR
Hardware taggingArm Memory Tagging Extension (MTE); CHERI (research, Morello prototype)Detects or blocks many spatial and temporal errors at hardware level
  • Testing: run AddressSanitizer and UndefinedBehaviorSanitizer builds in CI and continuous fuzzing on every parser. See the Fuzzing Guide.
  • Allocators: hardened allocators change exploitability. Google reports that a 2025 linear buffer overflow in Android's Rust CrabbyAVIF code (CVE-2025-48530) was caught before release, and that the Scudo hardened allocator's guard pages made it non-exploitable.
  • Isolation: Chromium's Rule of 2 approach of not combining untrusted input, an unsafe language and high privilege in one process is a useful design rule where code cannot yet be migrated.

The full baseline is in the OpenSSF Compiler Options Hardening Guide for C and C++; check flag support for your compiler versions before enforcing.

Where identity fits

Out-of-bounds reads matter to identity teams because process memory holds session tokens, API keys and passwords. Leaked memory turns a parsing bug into credential theft, and the stolen tokens remain valid until revoked. Plan for this in incident response: when a memory disclosure flaw is patched, rotate secrets and invalidate sessions that the vulnerable process held. See the Secrets Management Guide and the Token and Session Security Guide.

Detection and measurement

  • Monitor: new C and C++ files and new unsafe blocks per merge, sanitiser and fuzzing crashes, and CVEs in your products and dependencies tagged with memory safety CWEs.
  • Metric: share of new code in memory-safe languages per quarter, by product (target rising toward 100 percent after the cut-off date).
  • Metric: memory safety share of vulnerabilities as a percentage of all security fixes, using CWE data (the Android trend is the benchmark shape).
  • Metric: exposed memory-unsafe surface lines of C and C++ that handle untrusted input or run privileged, tracked downward.
  • Metric: unsafe density count of unsafe blocks or FFI functions per thousand lines in memory-safe code, with review coverage at 100 percent.
  • Metric: hardening coverage share of native build targets compiled with the agreed flag baseline and standard library hardening mode.

Framework mapping

FrameworkReferenceRelevance
NIST SP 800-53 Rev. 5SA-8 Security and Privacy Engineering Principles; SA-15 Development Process, Standards, and ToolsLanguage choice and toolchain standards as engineering controls
NIST SP 800-53 Rev. 5SA-11 Developer Testing and Evaluation, SA-11(1) Static Code Analysis, SA-11(8) Dynamic Code AnalysisSanitisers, fuzzing, Miri and static analysis
NIST SP 800-53 Rev. 5SI-16 Memory ProtectionRuntime protections such as non-executable memory and ASLR
NIST CSF 2.0PR.PS-06Secure software development practices integrated and monitored
ISO/IEC 27001:2022 Annex AA.8.25 Secure development life cycle; A.8.28 Secure codingLanguage and coding standards
CIS Controls v8.1Control 16 Application Software SecuritySecure development process and code-level safeguards
MITRE ATT&CKT1190 Exploit Public-Facing Application; T1203 Exploitation for Client Execution; T1068 Exploitation for Privilege EscalationTechniques that memory corruption bugs most often enable

Common failure patterns

  • Rewrite everything first: large rewrites stall and leave new C and C++ flowing in meanwhile. Stop the inflow with a new-code policy before planning rewrites.
  • Unreviewed unsafe and FFI: a Rust component full of raw pointers behind a thin wrapper inherits C's risks without C's review attention.
  • Forgetting native dependencies: a memory-safe service still parses data with a C library. MongoBleed shows the cost of length handling errors in native parsing code: in the MongoBleed (CVE-2025-14847) disclosure, the zlib message decompression path reported the allocated buffer size rather than the decompressed length, returning uninitialised heap memory, which could include credentials, to unauthenticated clients.
  • Treating over-reads as low severity: "only an information leak" is wrong when memory holds sessions. The CitrixBleed 2 (CVE-2025-5777) memory overread let unauthenticated attackers read leftover memory that researchers reported could contain user session tokens.
  • Hardening flags in the wrong builds: flags and hardening modes enabled for debug builds only, or overridden by a vendor default of no hardening.
  • No measurement: no CWE data on fixed vulnerabilities, so nobody can show whether the roadmap is working.

Practitioner checklist

  • Inventory C and C++ by component, exposure to untrusted input, privilege and owner, including native dependencies.
  • Publish a date after which new code is written in a memory-safe language, with an exception process.
  • Pick one self-contained, high-exposure component as a pilot and build the toolchain and interop once.
  • Ship replacements behind a flag with differential testing and fuzzing, keeping the old path for rollback.
  • Require safety comments, second review and CI reporting for every unsafe block and FFI binding; run Miri on unsafe code.
  • Enforce a compiler hardening baseline and standard library hardening mode on all remaining native builds.
  • Run sanitiser builds and continuous fuzzing on every parser of untrusted input.
  • Record CWE data for every fixed vulnerability and track the memory safety share over time.
  • Rotate secrets and invalidate sessions after any memory disclosure flaw in a process that held them.
  • Report roadmap progress to leadership and customers on a fixed cadence.

Standards and references

Related NHI Mgmt Group resources: Secure Coding Guide · CWE Top 25 Guide · Fuzzing Guide · Software Supply Chain Security Guide · Open Source Licence Compliance Guide

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Written and reviewed by Lalit Choda, NHI Mgmt Group. Last updated 24 October 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.