CVE-2026-21870 Overview
CVE-2026-21870 is an off-by-one stack-based buffer overflow in the BACnet Protocol Stack library. The flaw resides in the tokenizer_string function within src/bacnet/basic/program/ubasic/tokenizer.c. When the ubasic interpreter processes string literals at the maximum buffer length, it writes a null terminator to dest[40] even though the buffer only spans indices 0 through 39. This out-of-bounds write corrupts the stack and triggers a SIGABRT crash. The defect affects BACnet Stack versions 1.4.2, 1.5.0.rc1, and 1.5.0.rc2, as well as earlier releases. The vulnerability is tracked under [CWE-193: Off-by-one Error].
Critical Impact
Local attackers supplying crafted ubasic input can crash applications built on the BACnet Stack, denying availability of building automation services.
Affected Products
- Bacnetstack bacnet_stack versions up to and including 1.4.2
- Bacnetstack bacnet_stack 1.5.0.rc1
- Bacnetstack bacnet_stack 1.5.0.rc2
Discovery Timeline
- 2026-02-13 - CVE-2026-21870 published to NVD
- 2026-02-18 - Last updated in NVD database
Technical Details for CVE-2026-21870
Vulnerability Analysis
The BACnet Protocol Stack library exposes application layer, network layer, and media access (MAC) layer communications services for BACnet devices. It ships with a small ubasic interpreter used to run user-supplied BASIC programs against BACnet objects. The tokenizer parses string literals into a fixed-size stack buffer of 40 bytes. When a literal reaches the maximum length, the tokenizer writes a terminating null byte at offset 40, one byte past the end of the allocation. The resulting stack corruption causes the process to abort. An attacker who can submit ubasic source to a target application reliably crashes the service, denying availability of building automation logic.
Root Cause
The defect is a classic off-by-one error [CWE-193] in tokenizer_string. The function treats the buffer size of 40 as if it were the highest valid index rather than the number of bytes. Valid writes are confined to indices 0 through 39, but the null terminator is placed at index 40. Compilers commonly emit stack canaries for functions with character arrays, so the overflow is detected at function epilogue and the runtime aborts via __stack_chk_fail.
Attack Vector
Exploitation requires local access and user interaction to load a malicious ubasic program. The bug does not yield code execution under default builds because the stack canary halts the process before control flow can be hijacked. Confidentiality and integrity are not affected; the impact is limited to a high-impact loss of availability. Refer to the GitHub Security Advisory GHSA-pc83-wp6w-93mx for additional technical detail.
No public proof-of-concept exploit is available, and the issue is not listed in the CISA Known Exploited Vulnerabilities catalog.
Detection Methods for CVE-2026-21870
Indicators of Compromise
- Unexpected SIGABRT terminations of processes linked against libbacnet or embedding the ubasic interpreter.
- Core dumps showing __stack_chk_fail in the call stack with tokenizer_string as the originating frame.
- Repeated restarts of BACnet-enabled services after ingesting ubasic program input.
Detection Strategies
- Inventory all software that statically or dynamically links the BACnet Stack library and compare versions against 1.4.2, 1.5.0.rc1, and 1.5.0.rc2.
- Apply static analysis or fuzzing against tokenizer_string using 40-byte string literals to confirm the crash signature.
- Monitor process supervision logs for repeated abnormal terminations of BACnet daemons or gateways.
Monitoring Recommendations
- Forward operating system audit logs and core dump events to a centralized analytics pipeline for correlation.
- Alert on stack protector failures in long-running BACnet processes, which often indicate exploitation attempts of memory-safety bugs.
- Track file integrity changes to ubasic program files distributed to BACnet field controllers.
How to Mitigate CVE-2026-21870
Immediate Actions Required
- Upgrade BACnet Stack to a fixed revision that incorporates the patch in commit 4e1176394a5ae50d2fd0b5790d9bff806dc08465.
- Rebuild and redistribute any downstream products that statically link the affected versions of the library.
- Restrict who can supply ubasic source files to BACnet controllers and gateways.
Patch Information
The maintainers fixed the off-by-one in Pull Request 1196 by correcting the bounds check in tokenizer_string so the null terminator is written within the 40-byte buffer. Operators should pull the latest release from the bacnet-stack GitHub repository and validate the integration with their existing BACnet deployments before rolling it into production.
Workarounds
- Disable or remove the ubasic interpreter from builds where program execution on BACnet devices is not required.
- Enforce length limits on ubasic string literals upstream of the tokenizer, capping inputs well below the 40-byte boundary.
- Run BACnet services under a process supervisor that isolates crashes and prevents cascading service loss across building automation systems.
# Configuration example: pin the patched revision when building from source
git clone https://github.com/bacnet-stack/bacnet-stack.git
cd bacnet-stack
git checkout 4e1176394a5ae50d2fd0b5790d9bff806dc08465
make clean && make
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


