Skip to content

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.

Updated 02 Nov 2026Checked against cli@de9b52a
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 DEBUG or #ifndef NDEBUG (an #else branch 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 |= TRCENA used 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

  1. Wrap bring-up debug configuration in #ifdef DEBUG and make release builds define NDEBUG.
  2. Disable debug interfaces and enable readout protection (RDP level, APPROTECT, JTAG-disable fuses) for production.
  3. Enforce in CI that release artefacts are built with the production configuration.

References

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.

Edit this pageSources: cli/internal/sast/rules/vnx-1324.rego, cli/internal/sast/docs/vnx-1324.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.