VNX-1324: Hardware debug interface (JTAG/SWD) enabled in firmware outside a debug build
Reports firmware C/C++ code that enables or keeps alive a hardware debug port (STM32 DBGMCU, Cortex-M DHCSR C_DEBUGEN, SWJ remap, AVR JTD cleared, nRF APPROTECT disabled, JTAG/SWD enable flags) outside a #ifdef DEBUG / #ifndef NDEBUG block.
| Field | Value |
|---|---|
| Rule ID | VNX-1324 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | C, C++ |
| CWE | CWE-1324 |
| CAPEC | CAPEC-97 |
| ATT&CK | T1557 |
| CWSS vector | CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | firmware jtag swd debug-interface embedded cwe-1324 |
| Source | internal/sast/rules/vnx-1324.rego |
Overview
CWE-1324 is deprecated upstream; it described hardware debug interfaces (JTAG, SWD) left enabled in production devices, allowing physical access to extract firmware, read memory, or bypass security controls. This rule reports the firmware code that turns such a port on, or keeps it powered through low-power modes, when that code is not confined to a debug-only build.
Why This Matters
Hardware security researchers routinely use exposed JTAG/SWD interfaces to extract firmware, read secret keys from flash, and bypass secure boot. Debug-enabling code that is fine during bring-up often survives into release builds because nothing marks it as debug-only.
What Gets Flagged
DBGMCU->CR |= DBGMCU_CR_DBG_SLEEP | DBGMCU_CR_DBG_STOP; // FLAGGED
HAL_DBGMCU_EnableDBGStopMode(); // FLAGGED
CoreDebug->DHCSR = 0xA05F0001; // FLAGGED: C_DEBUGEN set
__HAL_AFIO_REMAP_SWJ_ENABLE(); // FLAGGED
MCUCR &= ~(1 << JTD); // FLAGGED: AVR JTAG re-enabled
NRF_UICR->APPROTECT = UICR_APPROTECT_PALL_HwDisabled; // FLAGGED
JTAG_ENABLE = 1; // FLAGGED
What Is Not Flagged
- The same code inside
#ifdef DEBUG,#if defined(DEBUG...),#if DEBUGor#ifndef NDEBUG(an#elsebranch of such a block is still reported). - Code that disables debug access:
&= ~(...),HAL_DBGMCU_Disable*(),DHCSR = 0xA05F0000,MCUCR |= (1 << JTD),APPROTECT_PALL_Enabled. CoreDebug->DEMCR |= TRCENAused for the DWT cycle counter.- Macro definitions, prototypes, comments and strings.
- Option bytes, eFuses and readout-protection levels set outside the source are not examined.
Remediation
- Wrap bring-up debug configuration in
#ifdef DEBUGand make release builds defineNDEBUG. - Disable debug interfaces and enable readout protection (RDP level, APPROTECT, JTAG-disable fuses) for production.
- Enforce in CI that release artefacts are built with the production configuration.
References
- CWE-1324: JTAG Interface (Deprecated)
- CWE-1191: On-Chip Debug and Test Interface With Improper Access Control
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-1324
// nosec vnx-1324
Or record an ignore rule: vulnetix ignore add --rule vnx-1324 --reason "...". See Suppressing findings.