Under attack? Get incident response help

info@angelforce.eu
Secure development

A memory-safety roadmap for C and C++ without a full rewrite

How product teams can cut C and C++ memory-safety risk this quarter with an inventory, isolation, fuzzing and a short, targeted rewrite list.

Also in:TürkçeDeutschFrançaisEspañolItalianoPolskiNederlandsEesti

Illustration: A memory-safety roadmap for C and C++ without a full rewrite

A memory-safety roadmap is a plan with owners and dates, and you can write one this quarter without touching most of your C and C++ code. The rewrite comes later and covers only the parts that justify it. What you need now is a clear picture of where unsafe code lives, a way to contain it, and a record of what you decided.

CISA's The Case for Memory Safe Roadmaps describes how software manufacturers can move to memory safe languages (MSLs) to eliminate memory safety vulnerabilities. It asks manufacturers to publish roadmaps so customers can see how they own security outcomes, practise radical transparency and take a top-down approach. Those are Secure by Design tenets, and the document is aimed at executives as well as engineers. That second audience matters: a roadmap without a sponsor stays in a wiki.

What the sources cover, and what they do not

The CISA summary page mentions only the transition to MSLs and the creation and publication of a roadmap. It does not show the full contents, so we make no claim about what the document says on fuzzing or process isolation. Those two steps below are our practice for the years between "we have C++ today" and "we have a safer language in the parts that matter". Treat them as interim controls, not as a substitute for the roadmap.

The sources also give no figures for how much risk any step removes. We will not invent them. Measure it yourself, from your own crash and vulnerability history.

Step 1: inventory the unsafe code

You cannot prioritise what you have not listed. Build a table per component, not per repository, because one repository often mixes a safe-to-leave utility with a network parser.

FieldWhy it matters
Language and standardShows what can and cannot be migrated
Reachable from outside?Network, file, USB, serial, update channel
Parses untrusted input?Decides fuzzing and rewrite priority
Runs with what privileges?Decides how much isolation helps
Third-party or ours?Decides who can fix it
Owner and last substantive changeDead code can often be removed

Include vendored libraries and firmware components. Hardware teams in particular tend to have old C code in bootloaders, drivers and update handlers that nobody has opened for years. Those components deserve a row.

Step 2: isolate what you cannot replace yet

For each component marked as reachable and parsing untrusted input, ask what happens if it is fully compromised. If the answer is "everything", that is your first design change. Move the parser into its own process, drop its privileges, and remove its access to files, sockets and keys it does not need.

This does not fix the bug. It limits what the bug is worth to an attacker. That fits the aim in NIST's Secure Software Development Framework (SP 800-218) of mitigating the potential impact of exploitation of vulnerabilities you have not yet found.

Step 3: fuzz the entry points

Take the components from your inventory that parse untrusted input and write a fuzz harness for each. Run the harnesses in CI with a time budget, and keep the crash corpus. Pick the file formats, protocol messages and update packages first, since those are the paths an outsider can reach.

Build the fuzzing binaries with the compiler's memory error detection switched on, so a silent overread becomes a visible failure. Every crash you triage gives you something the roadmap needs: evidence of which components deserve a rewrite. If a harness finds nothing after sustained runs, that is useful too, and it lets you rank that component lower.

Step 4: choose a short rewrite list

Use the first three steps to pick candidates. A good first rewrite has these properties:

  • It parses untrusted input.
  • It has a narrow interface, so it can be replaced behind the same API.
  • It has produced crashes under fuzzing or has a bug history.
  • It is small enough for one team to finish in a release cycle or two.

Leave stable, internal, non-exposed code in C or C++ and say so in the roadmap. Writing "not planned, isolated, fuzzed" next to a component is honest, and customers can work with it. This is our interpretation of radical transparency: you state the position, and not every row has to end in a rewrite. The CISA summary names the tenet but does not say what it means for components that stay in C or C++.

New components are the cheapest place to start. Decide now which language new network-facing code will use, and write that into your engineering standards.

Step 5: write it down and tie it to your process

NIST describes the SSDF as a core set of high-level practices that you integrate into whatever development life cycle you already run, with the aim of addressing root causes so vulnerabilities do not recur. Put your memory-safety rules into that existing process: language choice for new code, fuzzing in CI, a review gate for unsafe constructs. The SSDF also gives purchasers and suppliers a common vocabulary, which helps when a customer's security questionnaire asks about memory safety.

For coding checklists, the OWASP Secure Coding Practices Quick Reference Guide project is archived. Its checklists have moved into the OWASP Developer Guide, so use that version rather than a stale PDF.

Where to start

  1. Export a list of every C and C++ component, including vendored and firmware code, and fill in the inventory table above. Time-box it to two weeks.
  2. Mark the components that read untrusted input and list what each can access if compromised.
  3. Put the top three exposed components into separate, low-privilege processes, or schedule the change with a named owner.
  4. Write fuzz harnesses for those same components and run them in CI. Review crashes weekly.
  5. Choose one component for a rewrite in a memory safe language, and set a language rule for all new network-facing code.
  6. Publish a one-page internal roadmap with owners and dates, then decide what you share with customers. If you want an outside check, our secure software development service and penetration testing can review the inventory and test the isolated components.

How we can help

Secure software

We build security into software from the first commit, and we build security tools of our own.

Contact us
AngelForce team

Written by the AngelForce team: security consultants with CEH, LPT Master and CISA certifications who test, monitor and defend systems for organisations across Europe and Türkiye.

Written with AI assistance from public sources listed below, and reviewed by the AngelForce team before publication.

Sources

  1. www.cisa.gov/resources-tools/resources/case-memory-safe-roadmaps
  2. csrc.nist.gov/pubs/sp/800/218/final
  3. owasp.org/projects/secure-coding-practices-quick-reference-guide

Articles about Secure development

Tell us what you need to protect

Describe your environment and what you want to achieve. We will reply by email.

Contact us
info@angelforce.eu

AngelForce OÜ · Tallinn, Estonia