Skip to content

MS/TP COBS decode overflow

High
skarg published GHSA-8456-m9x4-j6mc Oct 4, 2026

Package

bacnet-stack

Affected versions

1.4.0 through 1.5.0

Patched versions

1.4.6, 1.5.2, 1.6.1, 1.7.0

Description

Summary

The BACnet MS/TP receive path decodes COBS frames into an output pointer inside the same fixed input buffer, but passes the full input-buffer size as the decode capacity. A long valid COBS payload can therefore write past the end of the actual remaining buffer.

Details

  • Affected file: src/bacnet/datalink/mstp.c
  • Affected function: MSTP_Receive_Frame_FSM
  • Root cause: cobs_frame_decode() receives &InputBuffer[Index + 1] as output, but receives InputBufferSize instead of InputBufferSize - (Index + 1) as output capacity.
  • Existing validation only checks (Index + 1) < InputBufferSize; it does not check that the decoded payload fits after that shifted output pointer.
  • The PoC is a direct project-code harness around src/bacnet/datalink/cobs.c that mirrors the vulnerable mstp.c call shape.
  • Reachability caveat: this package proves the MS/TP COBS decode memory-corruption primitive with a local source-backed harness. It does not send BACnet traffic to a real device and does not prove RCE.

PoC

Local reproduction:

cd ~/bacnet-stack
cd .bug-hunter/github-advisory-pocs/BUG-09-mstp-cobs-overflow
./build.sh
./run.sh
cat output.log
cat asan.log
size_t encoded_len = cobs_frame_encode(
    arena,
    INPUT_SIZE,
    payload,
    sizeof(payload));

size_t decode_offset = encoded_len;
size_t actual_remaining_capacity = INPUT_SIZE - decode_offset;

/*
 * Vulnerable shape:
 * output pointer  = arena + decode_offset
 * capacity passed = full INPUT_SIZE
 *
 * Correct capacity should be:
 * INPUT_SIZE - decode_offset
 */
size_t decoded_len = cobs_frame_decode(
    &arena[decode_offset],
    INPUT_SIZE,
    arena,
    encoded_len);

Expected result:

  • output.log shows actual_remaining_capacity=498, incorrect_capacity_passed=1507, and expected_overflow_bytes=502.
input_buffer_size=1507
encoded_len=1009
decode_offset=1009
actual_remaining_capacity=498
incorrect_capacity_passed=1507
decoded_payload_size=1000
expected_overflow_bytes=502
  • asan.log shows AddressSanitizer: heap-buffer-overflow in cobs_decode().
ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size 1
SUMMARY: AddressSanitizer: heap-buffer-overflow ... cobs_decode

Impact

  • Vulnerability class: out-of-bounds write.
  • Attacker prerequisites: ability to deliver a crafted BACnet MS/TP COBS frame to a stack instance that uses this receive path.
  • Affected deployment context: BACnet MS/TP datalink deployments with COBS frame types enabled.
  • Proven impact from PoC: local sanitizer-confirmed heap out-of-bounds write.
  • Reachability caveat: this package proves the parser/datalink decode primitive locally. It does not prove code execution.

Suggested Fix

Pass the true remaining output capacity to cobs_frame_decode(), or decode into a separate buffer whose full capacity matches the value passed to the decoder.

Remediation

Remediated by resolving buffer overflow in COBS frame decoding as suggested and added unit test for tight buffer handling in PR #1425.

Severity

High

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Adjacent
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

CVE ID

CVE-2026-82414

Weaknesses

Out-of-bounds Write

The product writes data past the end, or before the beginning, of the intended buffer. Learn more on MITRE.

Credits