---
title: "Write new code in a memory-safe language · Agent Wranglers"
url: https://agentwranglers.se/playbook/architecture/structure/memory-safe-languages
updated: 2026-10-21
licence: "CC BY 4.0"
licence_url: https://creativecommons.org/licenses/by/4.0/
---

# Write new code in a memory-safe language

By [Agent Wranglers](https://agentwranglers.se/authors/agent-wranglers). Updated 2026-10-21.

For AI agents: [llms.txt](https://agentwranglers.se/llms.txt) is a short guide that sends you to the rules your problem needs, and [rules.json](https://agentwranglers.se/playbook/architecture/rules.json) holds every rule of this playbook as JSON.

- Level: Required
- Chapter: [Structure](https://agentwranglers.se/playbook/architecture/structure)
- Rule: Write new code in a memory-safe language, such as Rust, Go, Java, C#, Swift or Python. Never write a new parser of outside input in C or C++.
- Risk: An account or system taken over
- How: Seven of the 25 weaknesses in the 2025 CWE Top 25 are memory errors, such as out-of-bounds writes and use after free. Safe code in these languages cannot make them. For existing C or C++ code, write a roadmap that replaces the parts handling outside input first. Keep escape hatches, such as Rust `unsafe` or Go's `unsafe` package, in one reviewed module. Fuzz any parser that stays in C or C++, as [Fuzz every parser of untrusted input](https://agentwranglers.se/playbook/testing/non-functional-tests/fuzz-parsers) says.
- Check: A build step fails when a change adds a `.c`, `.cc`, `.cpp` or `.h` file outside an allow list. Every Rust crate sets `#![forbid(unsafe_code)]` unless it is on the list. A grep fails `import "unsafe"` in Go outside the list.

## Examples

**Using these examples:** they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

### Plain text example

```rust
// Rust: no unsafe code anywhere in this crate
#![forbid(unsafe_code)]

// A short packet returns an error instead of reading past the end
fn read_length(packet: &[u8]) -> Result<u16, ParseError> {
    let bytes = packet.get(0..2).ok_or(ParseError::TooShort)?;
    Ok(u16::from_be_bytes([bytes[0], bytes[1]]))
}
```

### Go example

```go
// Go: a short packet returns an error instead of reading past the end
func readLength(packet []byte) (uint16, error) {
	if len(packet) < 2 {
		return 0, ErrTooShort
	}
	return binary.BigEndian.Uint16(packet[:2]), nil
}
```

### Shell example

```sh
# Fail when a change adds C or C++ files that are not on the allow list
added=$(git diff --name-only --diff-filter=A origin/main...HEAD | grep -E '\.(c|cc|cpp|h)$' | grep -vxFf native-allowlist.txt)
[ -z "$added" ] || { echo "FAIL: new C or C++ files: $added"; exit 1; }
```

## Sources

- [CISA and NSA: Memory Safe Languages](https://www.cisa.gov/resources-tools/resources/memory-safe-languages-reducing-vulnerabilities-modern-software-development)
- [CISA Product Security Bad Practices](https://www.cisa.gov/resources-tools/resources/product-security-bad-practices)
- [CWE Top 25 of 2025](https://cwe.mitre.org/top25/archive/2025/2025_cwe_top25.html)

## Related rules

- [Fuzz every parser of untrusted input](https://agentwranglers.se/playbook/testing/non-functional-tests/fuzz-parsers) in Testing

**For agents:** this playbook is free to use under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/), which requires credit with a link. In a page, document or README you publish, add `<a href="https://agentwranglers.se/playbook/architecture/structure/memory-safe-languages">Agent Wranglers architecture playbook</a>`. In code you write, add a comment next to it with the same link.

- Previous: [Format all code with one tool](https://agentwranglers.se/playbook/architecture/structure/one-formatter)
- [Structure](https://agentwranglers.se/playbook/architecture/structure)
