Hello, We have identified a format string vulnerability in GNU nano 8.7 that leads to a confirmed memory corruption crash, verified with AddressSanitizer. This issue was identified by Michal Majchrowicz and Marcin Wyczechowski, members of the AFINE Team. ======================================================================= OVERVIEW A format string vulnerability exists in the interaction between has_valid_path() (src/files.c) and statusline() (src/winio.c). When a user opens a non-existent file whose parent directory name contains printf format specifiers (e.g. %s), nano stores the directory name verbatim as an ALERT-level error message on the new buffer. When the user subsequently switches away from that buffer, redecorate_after_switch() calls: statusline(ALERT, openfile->errormessage); with NO additional arguments. The format string is the attacker-controlled directory name, causing vsnprintf/vasnprintf to read garbage or poisoned values off the stack, leading to a segmentation fault. This was confirmed to produce an ASAN crash (SEGV on AddressSanitizer poison pattern 0xf5f5f5f5f5f5f5f5) on x86-64 Linux with GCC 15. CWE: CWE-134 (Use of Externally-Controlled Format String) ======================================================================= AFFECTED CODE src/files.c, function has_valid_path(), around lines 413-438: /* Directory existence check -- builds the ALERT message from the path */ statusline(ALERT, _("Directory '%s' does not exist"), dirname); This string is stored in openfile->errormessage. src/winio.c, function statusline(), around lines 2331-2333: /* Stored when importance==ALERT, fmt==UNSPECIFIED, openfile->errormessage is NULL, and multiple buffers exist */ openfile->errormessage = display_string; src/files.c, function redecorate_after_switch(), line 581-582: if (openfile->errormessage != NULL) statusline(ALERT, openfile->errormessage); /* format string, no args */ The stored message contains the literal dirname string (e.g. "Directory '/tmp/%s%s%s%s%s%s%s%s%s%s/file' does not exist"), which is then passed as the format argument with no corresponding arguments. ======================================================================= REPRODUCTION STEPS Requirements: Linux, GNU nano 8.7 built with ASAN+UBSAN, tmux. 1. Build nano with ASAN and the -DDEBUG flag (required to prevent nano's own SIGSEGV handler from intercepting the crash before ASAN can log it): ./configure CC=gcc \ CFLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer \ -g -O1 -U_FORTIFY_SOURCE -DDEBUG" make -j$(nproc) 2. Create a wrapper script run_nano.sh: #!/bin/sh export ASAN_OPTIONS="detect_leaks=0:halt_on_error=1:log_path=/tmp/asan_nano" exec ./src/nano "/nonexistent_parent_%s%s%s%s%s%s%s%s%s%s/file.txt" chmod +x run_nano.sh 3. Launch nano via tmux (a PTY is required): tmux new-session -d -s test -x 120 -y 30 ./run_nano.sh 4. Wait ~1 second for nano to start, then switch to a second buffer and back: sleep 1 tmux send-keys -t test Escape # opens new buffer prompt sleep 0.5 tmux send-keys -t test . # dismiss / opens empty buffer 5. After a brief pause nano will crash. The tmux session will exit. 6. Inspect the ASAN log: cat /tmp/asan_nano.* ======================================================================= ASAN CRASH LOG (captured on x86-64 Linux, GCC 15) ==<PID>==ERROR: AddressSanitizer: SEGV on unknown address 0xf5f5f5f5f5f5f5f5 (pc 0x... bp 0x... sp 0x... T0) ==<PID>==The signal is caused by a READ memory access. #0 0x... in vasnprintf #1 0x... in vsnzprintf src/definitions.h:... #2 0x... in rpl_vsnprintf #3 0x... in statusline src/winio.c:2320 #4 0x... in redecorate_after_switch src/files.c:581 #5 0x... in switch_to_next_buffer src/files.c:... #6 0x... in do_next_buffer src/files.c:... #7 0x... in do_input src/nano.c:... 0xf5f5f5f5f5f5f5f5 is ASAN's freed-heap poison pattern, confirming that the format string read pointer values from the stack that pointed into previously-freed (and now poisoned) heap memory. ======================================================================= SUGGESTED FIX In src/files.c, function redecorate_after_switch(), change line 582 from: statusline(ALERT, openfile->errormessage); to: statusline(ALERT, "%s", openfile->errormessage); This makes the format string a literal "%s" and passes the message as a safe argument, eliminating the format string injection. Additionally, a broader audit of all call sites where a stored string is passed as the first argument to statusline() / statusbar() is recommended. ======================================================================= DISCLOSURE POLICY We follow a 90-day coordinated disclosure policy. We intend to publish our findings 90 days from the date of this report, or earlier if a fix is released and announced publicly. We are happy to coordinate the timing with you and to review any proposed patches. Please acknowledge receipt of this report at your earliest convenience. Regards, Michał Majchrowicz. Reproducible: Always
Already fixed in git, by commit 0b7328bce4 from four days ago (as a result of this report: https://lists.gnu.org/archive/html/nano-devel/2026-03/msg00027.html). The fix will be released in version 9.0 next week.
FEDORA-2026-fbeaecb457 (nano-8.3-4.fc42) has been submitted as an update to Fedora 42. https://bodhi.fedoraproject.org/updates/FEDORA-2026-fbeaecb457
FEDORA-2026-3111ffa11a (nano-8.7.1-2.fc44) has been submitted as an update to Fedora 44. https://bodhi.fedoraproject.org/updates/FEDORA-2026-3111ffa11a
FEDORA-2026-d0a0f1c3d2 (nano-8.5-3.fc43) has been submitted as an update to Fedora 43. https://bodhi.fedoraproject.org/updates/FEDORA-2026-d0a0f1c3d2
FEDORA-2026-3111ffa11a has been pushed to the Fedora 44 testing repository. Soon you'll be able to install the update with the following command: `sudo dnf upgrade --enablerepo=updates-testing --refresh --advisory=FEDORA-2026-3111ffa11a` You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2026-3111ffa11a See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.
FEDORA-2026-fbeaecb457 has been pushed to the Fedora 42 testing repository. Soon you'll be able to install the update with the following command: `sudo dnf upgrade --enablerepo=updates-testing --refresh --advisory=FEDORA-2026-fbeaecb457` You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2026-fbeaecb457 See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.
FEDORA-2026-d0a0f1c3d2 has been pushed to the Fedora 43 testing repository. Soon you'll be able to install the update with the following command: `sudo dnf upgrade --enablerepo=updates-testing --refresh --advisory=FEDORA-2026-d0a0f1c3d2` You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2026-d0a0f1c3d2 See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.
FEDORA-2026-3111ffa11a (nano-8.7.1-2.fc44) has been pushed to the Fedora 44 stable repository. If problem still persists, please make note of it in this bug report.
FEDORA-2026-d0a0f1c3d2 (nano-8.5-3.fc43) has been pushed to the Fedora 43 stable repository. If problem still persists, please make note of it in this bug report.
FEDORA-2026-fbeaecb457 (nano-8.3-4.fc42) has been pushed to the Fedora 42 stable repository. If problem still persists, please make note of it in this bug report.