Knowledge · Bare metal
Checking Keil firmware for known vulnerabilities
Ben Plannet, co-founder and CTO of LegacyMind GmbH · As of 5 October 2026
The short answer
You check firmware built with Keil MDK for CVEs in two steps: first establish which libraries in which versions are in the build, then match that list against vulnerability databases such as the NVD. The best file for this is the AXF, not the BIN. The AXF is an ELF file with symbols and sections from which CMSIS packs, the RTOS and TLS libraries can be read together with their versions.
Why the AXF and not the BIN
The Keil linker (armlink) writes the AXF as an ELF file. It holds the symbol table with the function names, the program sections and, depending on the project settings, debug information with source paths. A function name such as mbedtls_ssl_handshake or xTaskCreate shows that mbedTLS or FreeRTOS is linked. A source path such as FreeRTOS/v10.4.6 often names the version already.
The BIN is produced from it with fromelf and holds only the bytes written to flash. Symbols and paths are gone. What remains is text a library compiles in itself, such as a version string. Not every library does that.
Doing it by hand
- Read the packs from the project: the project file (.uvprojx) lists the software packs used, with vendor and version, under RTE.
- Find the linked libraries: fromelf --text -s firmware.axf (Arm) or arm-none-eabi-nm firmware.axf lists the symbols. Prefixes such as mbedtls_, lwip_, wolfSSL_ or osKernel name the library.
- Read compiler and toolchain: arm-none-eabi-readelf -p .comment firmware.axf shows which compiler built it.
- Look for versions: strings -a firmware.axf | grep -iE "version|v[0-9]+\.[0-9]+" finds version strings where a library compiles one in. Source paths in the debug information often carry the version in a folder name.
- Match: look up name and version as a CPE in the NVD dictionary and check the CVEs listed for it. Add the CISA KEV catalogue and ENISA's EUVD for vulnerabilities that are actively exploited.
- Check with the vendor: the pack vendor's release notes say from which version a vulnerability is fixed.
What LegacyMind does automatically
Microcontroller builds from Keil MDK, IAR or GNU Arm. Read: CMSIS packs, versioned from the pack vendor's own description, version records in the binary (for example RTX5) and versions from source paths (FreeRTOS, lwIP, mbedTLS, STM32Cube). Plus hardening (stack canary, MPU, privilege separation) and embedded keys.
Components with an evidenced version are matched against the vulnerability sources, and every version says where it was read: version record, source path or pack description. A version the binary does not evidence stays blank instead of guessed.
Accepted and recognised. Until the conversion to bytes is done, please upload the BIN or the AXF of the same build.
What the build tells you
| Source in the AXF | What it tells you |
|---|---|
| Symbol table | Which libraries are linked (function names) |
| Debug information | Source paths, often with the version in a folder name |
| Section .comment | Compiler and version, for example Arm Compiler 5.06 or 6.x |
| Version records | Versions a library stores itself, for example RTX5 |
| Text in the binary | Version strings, where the library compiles one in |
Questions
- Is the BIN enough for a vulnerability check?
- Partly. The BIN lacks symbols and paths; only text a library compiles in itself remains. If you have the AXF of the same build, use the AXF.
- Do I need the source code?
- No. The AXF carries enough information to determine the libraries and many versions. The project file (.uvprojx) helps on top, because it lists the packs with their versions.
- Does this work with IAR or GCC too?
- Yes. IAR Embedded Workbench writes an .out file, the GNU Arm compiler an .elf file. Both are ELF files and are read the same way.
- What about an Intel HEX file?
- HEX is a text encoding of the same bytes as the BIN. For the check the AXF is better, because the HEX holds no symbols.
Sources
Read on
Check your own image
The app and the reports are in German. Questions in English are welcome.