Introduction
A command injection vulnerability in one of Python's most popular CLI libraries turned every application using click.edit() into a potential shell execution vector. Pallets Click has over 17,400 GitHub stars and is deeply integrated across the Python ecosystem. Countless command line tools, developer utilities, and automation scripts are built on it, so CVE-2026-7246 has broad reach.
Click is the composable command line interface toolkit maintained by the Pallets Project, the open-source organization behind Flask. Developers use it to build CLI applications of every size, from small scripts to production tooling. A vulnerability in a core function like click.edit() can therefore affect a significant number of downstream projects and environments.
Technical information
Root cause
The flaw is in the edit_files() function in Click. The vulnerable code path wraps a user-supplied filename in double quotes and passes the resulting string directly to subprocess.Popen() with the shell=True parameter enabled. The quotes are the only protection. Click does not escape double quotes or any other shell metacharacters inside the filename, which is a classic CWE-77 (Command Injection) condition.
When an application constructs a command such as:
<editor> "user_supplied_filename"
the code assumes the double quotes will keep the filename together as a single argument. Because nothing inside the filename is escaped, an attacker can craft a value that breaks out of the quotes entirely.
Attack flow
An attacker exploiting this vulnerability would follow these steps:
-
Identify an application or tool that passes externally influenced filenames to
click.edit(). This could be a CLI tool that accepts a filename argument, a web application that triggers an editor session, or a developer tool that opens files from untrusted sources. -
Craft a malicious filename with shell metacharacters that escape the double quote wrapping. For example, a filename like:
legitimate"; <injected_command>; echo "
- When the application calls
click.edit()with this filename, theedit_files()function builds a shell command string. The command passed tosubprocess.Popen(shell=True)becomes something like:
editor "legitimate"; <injected_command>; echo ""
-
The shell reads this as three separate statements: the editor command on the truncated filename, the injected command, which runs with the privileges of the running process, and a harmless echo statement.
-
The injected command executes on the host system under the unprivileged account running the application.
The fix in version 8.3.3
The patch in version 8.3.3 changes how Click constructs these commands in two places:
| Component | Previous Vulnerable Behavior | Updated Secure Behavior |
|---|---|---|
| edit_files | Used shell=True with quoted filenames | Uses shlex.split to create an argv list and removes shell=True |
| pager | Relied on shell tokenization | Uses shlex.split to split pager commands into argv lists |
Click now uses shlex.split to tokenize the editor and pager command strings into proper argv lists for subprocess.Popen, and it no longer passes shell=True. Filenames are treated strictly as data arguments and never as executable shell code. This is the correct, well-established pattern for safe subprocess invocation in Python.
CVSS and severity context
The vulnerability has a CVSS v3.1 base score of 7.3 (7.2 in some sources), which is high severity. The score reflects a local attack vector, high complexity, and required user interaction. The attack vector is local rather than network-based, but the realistic attack scenarios (supply chain, developer tooling, CLI applications that process external input) still make this a meaningful risk in practice.
Affected systems and versions
| Version Range | Status |
|---|---|
| All versions of Pallets Click prior to 8.3.3 (including 8.3.2 and below) | Vulnerable |
| Version 8.3.3 and later | Fixed |
Any application, tool, or library that depends on Click and passes externally influenced filenames to click.edit() is potentially exposed. That covers projects that depend on Click directly and projects where another package pulls Click in as a transitive dependency.
Vendor security history
The Pallets Project handled this vulnerability in a coordinated, responsible way. It coordinated disclosure with the CERT Coordination Center and shipped the fix in release 8.3.3 on April 22, 2026, ahead of the public advisory on April 30, 2026. That gave downstream consumers a window to patch before full details were published.



