← Back to Feed CACHED · 2026-06-30 01:53:02 · CACHE_KEY CVE-2026-10644
CVE-2026-10644 · CWE-787 · Disclosed 2026-06-28

The Microchip SERCOM-G1 UART driver

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

A serial-port driver that drops one extra byte on the floor — and the floor happens to be your neighbor's stack frame

CVE-2026-10644 lives in Zephyr RTOS's drivers/serial/uart_mchp_sercom_g1.c, the SERCOM-G1 UART driver used by the Microchip PIC32CM-JH SoC family. When a consumer calls uart_rx_enable() with a one-byte receive buffer while CONFIG_UART_MCHP_ASYNC=y, the RX-complete ISR kicks off a single-beat DMA transfer *while a byte is already pending in the SERCOM DATA register*. The result: one attacker-controlled byte written exactly one address past the end of the caller's RX buffer. Affected: Zephyr v4.4.0. Fixed: v4.5.0 (commit 5251d2b), which reads the first byte via CPU and only DMAs len-1 for larger buffers.

Vendor severity is MEDIUM (4.2) with vector AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:L — adjacent network, high complexity, low integrity, low availability. That matches reality, and arguably overstates it. The bug is single-byte, the value is bounded by what a wired UART peer can transmit, the location is fixed (immediately after the buffer), the async path is not enabled in default in-tree PIC32CM-JH board configs, and the consumer code must independently choose to pass a 1-byte buffer. Calling this MEDIUM is generous; we're downgrading to LOW.

"Single-byte OOB in an opt-in async UART path on one Microchip SoC family. Needs adjacent network, hard race, and a 1-byte RX buffer. Backlog hygiene."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Physical/adjacent UART access

The attacker needs to be the serial peer on the SERCOM UART line of a PIC32CM-JH-based device. This is AV:A in CVSS terms but in practice means wired access to a board's UART pins, a USB-serial bridge, a connected modem/sensor, or a compromised peripheral on the same bus.
Conditions required:
  • Physical or board-adjacent access to the UART line
  • Target firmware built on Zephyr v4.4.0 SERCOM-G1 driver
Where this breaks in practice:
  • Embedded devices using this SoC are typically inside sealed enclosures
  • UART is rarely exposed beyond debug headers in production
Detection/coverage: None — UART traffic is not visible to host scanners or EDR
STEP 02

Target enables async RX with len == 1

The application firmware must have been compiled with CONFIG_UART_MCHP_ASYNC=y (an opt-in Kconfig) AND must call uart_rx_enable(dev, buf, 1, timeout) with a one-byte buffer. Most realistic async consumers use ring buffers larger than one byte; one-byte async RX is an unusual API pattern.
Conditions required:
  • CONFIG_UART_MCHP_ASYNC=y in the firmware build
  • Caller passes len == 1 to uart_rx_enable()
Where this breaks in practice:
  • Default in-tree PIC32CM-JH board configs do not enable async UART
  • One-byte async DMA RX is a degenerate use case — most consumers batch
Detection/coverage: SBOM scanners (Black Duck, Snyk, JFrog) flag Zephyr 4.4.0 SERCOM-G1; static analysis can grep for uart_rx_enable(..., 1, ...)
STEP 03

Race the ISR

The attacker times a byte arrival to land in the SERCOM DATA register *before* the RX-complete ISR fires and starts the DMA transfer. This requires bit-level timing on the UART line relative to the MCU's interrupt latency — hence AC:H.
Conditions required:
  • Ability to drive precise UART timing
  • Knowledge of target baud rate and interrupt latency
Where this breaks in practice:
  • Race window is a few microseconds at typical UART baud rates
  • Most real peers (sensors, modems) cannot emit bytes with sub-symbol precision
Detection/coverage: Not detectable post-hoc; no telemetry from the SERCOM peripheral
STEP 04

One-byte adjacent corruption

The DMA controller writes one byte past the RX buffer. The value is the byte the attacker transmitted; the offset is fixed. The attacker influences *what* lands there but not *where* — placement is dictated by the linker's layout of whatever object sits immediately after the RX buffer (stack frame slot, adjacent struct member, or .bss neighbor).
Conditions required:
  • Knowledge or guess of memory layout adjacent to the RX buffer
Where this breaks in practice:
  • No control over destination address
  • No primitive to chain into code execution from a single fixed-offset byte
  • Most adjacent bytes are padding, canaries, or unrelated state
Detection/coverage: Crashes (HardFault) may surface in device logs if logging survives the corruption
STEP 05

Crash or transient state corruption

Realistic outcome is a HardFault / watchdog reset if the overwritten byte lands in a pointer LSB or critical state. In rare layouts where the adjacent byte is a flag or length field, the attacker may flip a boolean or nudge a counter. There is no documented path from this to RCE on the PIC32CM-JH.
Conditions required:
  • Adjacent byte is functionally meaningful
Where this breaks in practice:
  • Cortex-M0+ on PIC32CM-JH has no W^X enforcement to bypass, but also no useful gadget chain from a single byte
  • Watchdog reset is the most common outcome
Detection/coverage: Device reset counters; serial console panic traces
03 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationNone observed. No public reports of exploitation against PIC32CM-JH Zephyr deployments.
Public PoCNo weaponized PoC. The fix commit 5251d2b describes the race precisely enough to reproduce in a lab.
EPSS0.00143 (~0.14%) — bottom percentile, consistent with embedded-driver DoS bugs that have no internet attack surface.
KEV statusNot listed. Extremely unlikely to ever appear — CISA KEV catalogs internet-reachable bugs.
CVSS vectorAV:A/AC:H/PR:N/UI:N/S:U/C:N/I:L/A:L → adjacent, high complexity, no auth, no UI, scope unchanged, low integrity + low availability. No confidentiality impact at all.
Affected versionsZephyr RTOS v4.4.0 with CONFIG_UART_MCHP_ASYNC=y, SERCOM-G1 UART driver, PIC32CM-JH SoC family
Fixed versionZephyr v4.5.0 (mainline commit 5251d2bc0070be801769fb7ce7b9066fef5d9f81); backport to any 4.4-LTS forks must be picked manually
Exposure dataNot applicable — no public scanner (Shodan, Censys, GreyNoise) enumerates embedded SERCOM peripherals. Exposure is bounded by your PIC32CM-JH BOM.
Disclosed2026-06-28 via Zephyr GHSA GHSA-xv2x-56j7-6wc3
Reporterd3zd3z (Zephyr community contributor); reported and patched through the Zephyr security advisory process
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to LOW (2.8/10)

The single decisive factor is attacker position: this bug requires wired UART-peer access to a specific Microchip SoC running an opt-in async config with a degenerate 1-byte buffer, and the primitive is a single fixed-offset byte with no path to code execution. Blast radius is one device, capped at crash or watchdog reset.

HIGH Technical assessment of the primitive (single-byte adjacent OOB with attacker-controlled value, fixed offset)
HIGH Exploitability ceiling (no RCE path documented or plausible from this primitive on Cortex-M0+)
MEDIUM Installed-base estimate — PIC32CM-JH async UART consumers are a niche subset of Zephyr deployments

Why this verdict

  • Attacker position is adjacent/wired, not network. No remote reachability. The attacker is already on the UART line — a position from which countless simpler attacks (replay, fuzzing, JTAG if exposed) exist.
  • Three independent preconditions must all hold: (a) firmware built from Zephyr v4.4.0 SERCOM-G1, (b) CONFIG_UART_MCHP_ASYNC=y (not default), (c) a consumer that calls uart_rx_enable with len == 1 (an unusual API shape). The intersection is small.
  • Primitive ceiling is one byte at a fixed offset. Attacker controls the value, not the address. There is no documented or plausible chain from this primitive to RCE on Cortex-M0+ class parts — outcome is HardFault / watchdog / transient state flip.
  • Role multiplier: PIC32CM-JH is a general-purpose Cortex-M0+ MCU used in motor control, IoT endpoints, and consumer devices — not identity, hypervisor, PKI, or supply-chain roles. There is no canonical high-value deployment role for this SoC that elevates blast radius beyond one device. The deployment-role floor does not trigger.
  • EPSS 0.00143 + no KEV + no public PoC weaponization — all empirical signals align with the technical floor.

Why not higher?

MEDIUM would imply a believable path to disrupt multiple devices or a privilege transition. Neither exists: the primitive is one byte at one fixed offset on one device, requires wired access plus a hard race, and the affected config is opt-in. Vendor's 4.2 is itself charitable.

Why not lower?

IGNORE is wrong because the bug is real, the patch is straightforward, and embedded firmware updates are operationally expensive — so teams shipping PIC32CM-JH devices should still pick up the fix on their normal Zephyr LTS cadence rather than declare it unfixable noise.

05 · Compensating Control

What to do — in priority order.

  1. Audit firmware for CONFIG_UART_MCHP_ASYNC and len==1 callers — Grep your Zephyr application tree for CONFIG_UART_MCHP_ASYNC in prj.conf/Kconfig fragments and for uart_rx_enable(.*,\s*1\s*, call sites. If neither is present, you are not vulnerable regardless of Zephyr version. noisgate MEDIUM/LOW SLA: no mitigation deadline — fold into the 365-day remediation window.
  2. Pin async UART consumers to len ≥ 2 — If you must keep async mode on Zephyr 4.4.0, refactor consumers to use a minimum 2-byte RX buffer. The bug is specifically the len == 1 single-beat DMA path; len ≥ 2 follows the safe code path and is immune.
  3. Disable physical UART access on production units — Conformal-coat or remove debug headers, disable test-mode pins via fuse settings on PIC32CM-JH, and ensure production firmware does not expose a privileged UART console. This caps any future UART-driver bug at the same time.
  4. Schedule rebase to Zephyr 4.5.0 or backport commit 5251d2b — On your normal Zephyr LTS cadence, rebase to 4.5.0 or cherry-pick 5251d2bc0070be801769fb7ce7b9066fef5d9f81 into your 4.4-based fork. Roll into the next scheduled firmware OTA — no emergency drop needed.
What doesn't work
  • Network segmentation / firewalls — the attack vector is AV:A over a wired UART line, not IP. Nothing on your network plane changes the attack surface.
  • ASLR / stack canaries — Cortex-M0+ Zephyr builds typically run from flash with static .bss/.data layouts and no meaningful ASLR; canaries don't cover a single-byte adjacent write to a non-stack object.
  • EDR / SIEM rules — there is no host telemetry from a SERCOM DMA peripheral. No detection content exists or can be reasonably authored.
  • SBOM scanners alone — they will flag Zephyr 4.4.0 but cannot tell you whether CONFIG_UART_MCHP_ASYNC is enabled or whether any caller uses a 1-byte buffer. You still need source-level audit.
06 · Verification

Crowdsourced verification payload.

Run this on your build host (or in CI) against the root of a Zephyr application tree. Invoke as ./check_cve_2026_10644.sh /path/to/zephyr-app. No special privileges required — it greps source files and Kconfig fragments to determine whether the vulnerable async + len==1 combination is reachable in your build.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cve_2026_10644.sh — Zephyr SERCOM-G1 UART async OOB write check
# Usage: ./check_cve_2026_10644.sh <path-to-zephyr-app-or-tree>
# Exit: 0 PATCHED, 1 VULNERABLE, 2 UNKNOWN
set -u
ROOT="${1:-.}"
if [ ! -d "$ROOT" ]; then
  echo "UNKNOWN: path '$ROOT' is not a directory" >&2
  exit 2
fi

# 1. Detect Zephyr version (VERSION file at repo root)
VER_FILE="$(find "$ROOT" -maxdepth 4 -name VERSION -path '*/zephyr/VERSION' 2>/dev/null | head -n1)"
if [ -z "$VER_FILE" ]; then
  VER_FILE="$(find "$ROOT" -maxdepth 2 -name VERSION 2>/dev/null | head -n1)"
fi
ZVER="unknown"
if [ -n "$VER_FILE" ] && [ -f "$VER_FILE" ]; then
  MAJ=$(grep -E '^VERSION_MAJOR' "$VER_FILE" | awk -F'=' '{print $2}' | tr -d ' ')
  MIN=$(grep -E '^VERSION_MINOR' "$VER_FILE" | awk -F'=' '{print $2}' | tr -d ' ')
  PAT=$(grep -E '^PATCHLEVEL'    "$VER_FILE" | awk -F'=' '{print $2}' | tr -d ' ')
  ZVER="${MAJ}.${MIN}.${PAT}"
fi
echo "Detected Zephyr version: $ZVER"

# 2. Look for the vulnerable driver file
DRV="$(find "$ROOT" -type f -name 'uart_mchp_sercom_g1.c' 2>/dev/null | head -n1)"
if [ -z "$DRV" ]; then
  echo "PATCHED: SERCOM-G1 UART driver not present in tree"
  exit 0
fi

# 3. Check whether async UART is enabled anywhere in the application config
ASYNC_HITS=$(grep -RIl --include='*.conf' --include='Kconfig*' --include='*.cmake' \
             -E 'CONFIG_UART_MCHP_ASYNC[[:space:]]*=[[:space:]]*y' "$ROOT" 2>/dev/null | wc -l)

# 4. Look for len==1 uart_rx_enable call sites
LEN1_HITS=$(grep -RInE 'uart_rx_enable[[:space:]]*\([^,]+,[^,]+,[[:space:]]*1[[:space:]]*,' "$ROOT" 2>/dev/null | wc -l)

# 5. Confirm patch presence: fixed driver reads first byte via CPU
if grep -qE 'uart_poll_in|read.*first.*byte.*CPU|len[[:space:]]*-[[:space:]]*1' "$DRV" 2>/dev/null; then
  PATCH_PRESENT=1
else
  PATCH_PRESENT=0
fi

echo "async enabled in configs: $ASYNC_HITS file(s)"
echo "uart_rx_enable len==1 call sites: $LEN1_HITS"
echo "patch markers present in driver: $PATCH_PRESENT"

# Decision
if [ "$ZVER" = "4.4.0" ] && [ "$ASYNC_HITS" -gt 0 ] && [ "$LEN1_HITS" -gt 0 ] && [ "$PATCH_PRESENT" -eq 0 ]; then
  echo "VULNERABLE: Zephyr 4.4.0 + async UART + 1-byte RX buffer + unpatched driver"
  exit 1
fi

if [ "$PATCH_PRESENT" -eq 1 ] || [ "$ASYNC_HITS" -eq 0 ] || [ "$LEN1_HITS" -eq 0 ]; then
  echo "PATCHED: vulnerable combination not reachable in this build"
  exit 0
fi

echo "UNKNOWN: version=$ZVER async=$ASYNC_HITS len1=$LEN1_HITS patch=$PATCH_PRESENT — manual review needed"
exit 2
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: do not treat this as an emergency. Per the noisgate mitigation SLA for LOW, there is no mitigation deadline. Per the noisgate remediation SLA, this is a 365-day backlog item — fold the Zephyr 4.5.0 rebase (or a cherry-pick of commit 5251d2b) into your next routine firmware release. Before then, run the verification script across your application repos: if you don't ship PIC32CM-JH devices, or you don't set CONFIG_UART_MCHP_ASYNC=y, or no caller uses a 1-byte uart_rx_enable, you can document this as not-applicable and move on. If you do meet all three conditions, refactor offending callers to ≥2-byte buffers as a same-day interim and ship the patched driver on your normal OTA cadence.

Sources

  1. Zephyr GHSA-xv2x-56j7-6wc3 advisory
  2. Fix commit 5251d2b in zephyrproject-rtos/zephyr
  3. NVD entry for CVE-2026-10644
  4. Vulnerability-Lookup (CIRCL) CVE-2026-10644
  5. THREATINT CVE-2026-10644
  6. Zephyr SERCOM-G1 UART devicetree binding
  7. CWE-787: Out-of-bounds Write
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.