CVE-2026-4519 Overview
CVE-2026-4519 affects the Python standard library webbrowser module. The webbrowser.open() API accepted URLs containing leading dashes, which certain web browsers parse as command line options rather than as a URL target. An attacker who can influence the URL string passed to webbrowser.open() can therefore smuggle arbitrary browser flags into the underlying browser process. The issue is classified as Improper Input Validation [CWE-20]. Updated Python builds reject leading dashes, and the Python Security Response Team recommends sanitizing URLs before passing them to webbrowser.open().
Critical Impact
A crafted URL string can be interpreted as browser command line flags, enabling local argument injection that may compromise confidentiality and integrity of the user session.
Affected Products
- CPython webbrowser module across maintained 3.x branches
- Python 3.15.0 pre-release builds (alpha1 through alpha7)
- Applications and libraries that pass untrusted input to webbrowser.open()
Discovery Timeline
- 2026-03-20 - CVE CVE-2026-4519 published to NVD
- 2026-04-16 - Last updated in NVD database
Technical Details for CVE-2026-4519
Vulnerability Analysis
The webbrowser module in CPython launches an external browser by building a command line and invoking the browser binary through the subprocess family of APIs. The URL argument is appended directly to the browser command without validating that it is structurally a URL. Many browsers accept long-form flags such as --app=, --remote-debugging-port=, or --user-data-dir= as positional arguments. If a URL begins with - or --, the browser process treats it as an option, not a navigation target.
Attackers leverage this to alter browser behavior at launch. Examples include forcing the browser into application mode pointing at attacker content, redirecting the user profile to a writable directory, or enabling remote debugging interfaces that expose the browsing session. The vulnerability requires that attacker-controlled data reach webbrowser.open(), which is common in desktop tools, help systems, and CLI utilities that resolve documentation or external links.
Root Cause
The root cause is missing input validation on the URL parameter to webbrowser.open(). The module trusted the caller to provide a well-formed URL and forwarded the string to the browser as an argv element. Because POSIX and Windows browsers treat leading - tokens as switches, the argument boundary between option and URL collapses. The fix in CPython rejects URLs whose first character is -, restoring the expected separation between flags and the target URL.
Attack Vector
The attack vector is local and requires user interaction. The adversary supplies a malicious URL through a channel that a Python application later opens with webbrowser.open(). Typical sources include shortcut files, registered URL handlers, configuration files, command line arguments parsed by a Python tool, or content rendered in a desktop application. When the application calls webbrowser.open(url) with a value like --remote-debugging-port=9222, the browser starts with the attacker-chosen flag rather than navigating to a site.
No verified public exploit code is available at this time. Refer to the Python Security Announcement Thread and GitHub Issue #143930 for additional technical context.
Detection Methods for CVE-2026-4519
Indicators of Compromise
- Browser child processes spawned by python or python3 with command line arguments beginning with - or -- instead of http:// or https://.
- Unexpected use of browser flags such as --remote-debugging-port, --user-data-dir, --app, or --load-extension immediately after a Python process executes.
- New browser profile directories or extension loads originating from Python-launched browser sessions.
Detection Strategies
- Audit source code and dependencies for calls to webbrowser.open(), webbrowser.open_new(), and webbrowser.open_new_tab() that consume untrusted input.
- Use EDR process telemetry to alert when a Python interpreter is the parent of a browser process whose first URL argument starts with -.
- Apply static analysis rules (Bandit, Semgrep) that flag webbrowser.open(x) where x is not a literal or validated string.
Monitoring Recommendations
- Centralize process creation events from Windows, macOS, and Linux endpoints to identify anomalous browser launch flags.
- Track Python application updates and confirm that runtime versions include the fix commits listed in the CPython advisory.
- Alert on Python tools that launch browsers with debugging or extension-loading flags outside of approved developer workflows.
How to Mitigate CVE-2026-4519
Immediate Actions Required
- Upgrade to a CPython release that includes the fix commits referenced in the CPython security patch series.
- Inventory internal applications that call webbrowser.open() and validate every URL argument against a strict allowlist scheme such as http, https, mailto, or file.
- Reject any URL whose first character is - before invoking the webbrowser module.
Patch Information
The Python maintainers landed a series of commits across supported branches that reject URLs beginning with a leading dash. Relevant fixes include commit 3681d47a, commit 43fe06b9, and the consolidating pull request #143931. Apply distribution updates that ship these commits, or upgrade to the next patch release on each supported 3.x branch.
Workarounds
- Wrap calls with a validator: parse the URL using urllib.parse.urlsplit, require a known scheme, and abort if the raw string begins with -.
- Prefix relative or scheme-less inputs with https:// after validation to ensure the argument cannot be interpreted as a flag.
- For applications that cannot upgrade immediately, replace webbrowser.open() with a controlled wrapper that invokes the browser through subprocess using an explicit -- argument separator where the target browser supports it.
# Configuration example: sanitize before calling webbrowser.open()
python - <<'PY'
import sys
from urllib.parse import urlsplit
import webbrowser
def safe_open(url: str) -> bool:
if not url or url[0] == '-':
return False
parts = urlsplit(url)
if parts.scheme not in {'http', 'https', 'mailto', 'file'}:
return False
return webbrowser.open(url)
sys.exit(0 if safe_open(sys.argv[1]) else 1)
PY
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.


