Safeguard
Security Guides•

Which languages are memory safe, and where the guarantee ends

Rust, Go, Java, C#, Swift, Python and JavaScript are called memory safe, but each guarantee has edges. Here is what holds and where it stops.

Safeguard Security Team
3 min read

Rust, Go, C#, Java, Swift, Python and JavaScript are generally listed as memory safe, and C, C++ and assembly are not. The guarantee is real but conditional: it covers safe code, and it stops at unsafe blocks, native extensions, foreign function calls and, in some languages, data races.

What the lists say

The memorysafety.org project names Rust, Go, C#, Java, Swift, Python and JavaScript as memory safe, and C, C++ and assembly as not. CISA and the NSA publish guidance on adopting memory safe languages, and the White House technical report from February 2024 says there are dozens of them.

Treat these lists as a starting point. The question for your project is which edges of the guarantee you will actually touch.

Edge one: unsafe escape hatches

Rust lets you opt out of some compiler checks inside an unsafe block. The Rust book lists five things unsafe allows: dereferencing a raw pointer, calling an unsafe function, accessing a mutable static, implementing an unsafe trait and accessing union fields. It does not switch off the borrow checker. Still, a mistake in those spots can cause real memory bugs.

Edge two: foreign code

Most memory safe languages can call into C. Python extension modules, Java native interfaces and Rust FFI all pull C or C++ into the process. The Rust Reference warns that undefined behavior in one language, including C reached through FFI, affects the whole program. Your safe wrapper is only as safe as the library behind it.

Edge three: data races in Go

The Go memory model says races on multiword values such as interfaces, maps, slices and strings can, in most implementations, lead to arbitrary memory corruption, because the pointer and length pairs can be observed inconsistently. Go gives you a race detector through go build -race, and the model advises that programs modifying data used by several goroutines must serialize access.

Edge four: the runtime and the compiler

Garbage collected runtimes, interpreters and just in time compilers are themselves large bodies of C or C++. A bug there can break the guarantee beneath your safe code. This is one reason to keep runtimes patched, and a reason a dependency inventory includes the runtime.

A practical reading

  1. Safe language, no unsafe, no native dependencies: the strongest case.
  2. Safe language with a few audited unsafe blocks: still a large reduction in attack surface.
  3. Safe language wrapping a big native library: you inherit that library's risk.

Try it yourself

Click through it at your own pace, or open it full screen. Look for packages that bring native code with them, which is where the guarantee usually ends.

Quick check

Does Rust unsafe disable the borrow checker?

No. The Rust book says unsafe does not turn off the borrow checker or other safety checks. It only unlocks five specific operations the compiler cannot verify.

Can a Go program corrupt memory?

Yes, through data races on values such as slices, maps, strings and interfaces, according to the Go memory model. Avoiding races is how you keep the guarantee.

Safeguard's dependency scanning can list the native libraries your safe language projects pull in, which is where the guarantee usually ends.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.