
Notepad++ CVE-2026-52886 — session.xml backupFilePath starts_with() path traversal (GHSA-rqfm-pw34-r7j6)
starts_with() Prefix Check BypassNotepad++ — Arbitrary File Read via session.xml backupFilePath Traversal
PowerEditor/src/Notepad_plus.cpp (session restore — backupFilePath validation)session.xml)Notepad++ validates the backupFilePath attribute during session restoration using a raw string prefix comparison via std::wstring::starts_with(), without normalizing the path first. A crafted path that begins with the legitimate backup directory prefix but contains ..\ traversal sequences passes the check, yet resolves to an arbitrary location when the OS opens the file — loading the content of any readable file into an editor tab.
On launch with snapshot (backup) mode enabled, Notepad++ restores the previous session from session.xml. Each entry's backupFilePath is expected to live under the application's backup directory. The integrity gate only checks that the stored path starts with the expected backup directory string. Because the comparison happens on the raw, un-normalized string, an attacker prepends the legitimate prefix and then walks out of the directory with ..\ sequences.
The check tests a textual prefix; the use opens the OS-resolved path. The two disagree once ..\ is present.
| Operation | Source | Behavior |
|---|---|---|
| CHECK | Raw backupFilePath string | starts_with(backupDir) — passes on prefix match |
| USE | OS-resolved path | ..\ sequences collapse to an arbitrary location |
Pre-condition: Write access to session.xml, snapshot/backup mode enabled.
Steps:
session.xml, injecting a crafted backupFilePath:
<backupDir>\..\..\..\..\Users\victim\.ssh\id_rsa<backupDir>\ satisfies starts_with(), so validation passes...\ sequences; the target file is opened.Result: Read-only exfiltration — target file content is visible in the editor, including sensitive files such as SSH keys, environment configuration files, and credential stores.
.env / config files, credential stores — any file readable by the userRequirements:
session.xmlbackupFilePath payload: backup directory prefix + ..\ traversal sequences + target file pathInjecting the crafted path and launching the application loads the target file into an editor tab.
The fix (commit 7e66f36) performs proper path normalization before validation, so ..\ sequences are collapsed prior to the prefix comparison — the checked path and the used path now agree.