Skip to main content

JupyterLab EUVDEUVD-2026-89337

| CVE-2026-102830 MEDIUM
Cross-site Scripting (XSS) (CWE-79)
2026-09-29 security-advisories@github.com GHSA-3jqq-pw4j-pqcj
6.8
CVSS 3.1 · Vendor: github
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Publish malicious third-party language pack
  2. Delivery
    Victim installs and selects locale
  3. Exploit
    Prefix-only regex accepts appended JS
  4. Execution
    new Function executes code in authenticated origin
  5. Persist
    Call authenticated Jupyter Server APIs
  6. Impact
    Read/modify files and run kernel code

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A05:2025 - Injection
ASVS 5.0
V1 - Encoding and Sanitization Output encoding, context-aware escaping
MITRE ATT&CK

2 techniques across 2 tactics: Initial Access, Execution

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

Exploitation requires a victim to install AND activate a malicious or tampered third-party JupyterLab language pack (locale/translation catalogue); the default English locale is unaffected because it loads no catalogue. The Plural-Forms header must carry a valid plural rule as a matching prefix followed by appended JavaScript, which the prefix-only regex (missing end-anchor) accepts and passes to new Function. Full server-side impact (file read/modify, code execution) additionally requires that Jupyter Server kernels, terminals, and APIs are exposed to the JupyterLab origin - in JupyterLite these surfaces are typically absent, sharply limiting impact. Limiting factors: high attack complexity (crafted locale must be delivered and chosen by the user), required user interaction (locale selection), and dependence on a non-default third-party language pack.

Impact

The provided CVSS 3.1 vector (AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N) yields 6.8 (Medium) and is internally consistent with the description: exploitation is network-reachable but requires both a high-complexity precondition (the victim must select a malicious third-party language pack) and user interaction (UI:R). No EPSS score, KEV listing, or public POC is present in the input, so this is 'no public exploit identified at time of analysis' - though the fix commit ships a regression test (985a3223) that demonstrates the injection primitive (globalThis.__jupyterLabTranslationXss = true;), which is effectively a proof of the technique but not a weaponized exploit. There is no signal conflict: the low real-world exploitation likelihood stems from the multi-step social/supply-chain requirement (attacker must get a victim to install and activate a crafted locale pack), not from any contradiction in the data. This is best treated as a legitimate but non-emergency patch priority: a genuine code-injection-in-authenticated-origin flaw whose blast radius (read/modify files, run kernel code via authenticated Jupyter Server APIs) is severe, but whose trigger conditions make mass or opportunistic exploitation unlikely. Impact is materially lower on JupyterLite, which usually lacks the exposed Jupyter Server surfaces.

Exploit ScenarioDerived

An attacker publishes or tampers with a third-party JupyterLab language pack whose Plural-Forms header contains a valid plural rule followed by appended JavaScript. A user installs and selects that locale; when JupyterLab loads the catalogue and translates any plural string, the appended code runs via new Function in the authenticated JupyterLab origin, letting it call authenticated Jupyter Server APIs to read/modify files and execute code on the server. No public weaponized exploit is identified, though the vendor fix includes a regression test proving the injection.

This Month Plan within 30 days. Why: MEDIUM severity (CVSS 4.0-6.9).
Patch available 0.3% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – Sep 29, 2026

Code injection in JupyterLab's translation pipeline allows JavaScript appended to a third-party language pack's Plural-Forms header to be executed in the authenticated JupyterLab origin, because the validation regex accepts a matching prefix without requiring the whole header to match and the expression is later passed to new Function. Affected are JupyterLab 3.0.0 through 4.5.11 and 4.6.4 (exclusive of the fixes), plus JupyterLite Core 0.8.3 and earlier. Exploitation requires the victim to install and select a malicious or tampered third-party locale catalogue (the default English locale loads no catalogue and is unaffected), and unauthenticated remote attackers need user interaction (CVSS:3.1/AV:N/AC:H/PR:N/UI:R), yielding a Medium severity of 6.8; where Jupyter Server kernels, terminals, and APIs are exposed to the JupyterLab origin the injected code can read or modify files and run code, while JupyterLite impact is sharply limited by the usual absence of those surfaces. No public exploit code was identified at time of analysis and the issue is not confirmed actively exploited (CISA KEV).

RemediationAI

Upgrade to a patched release: JupyterLab 4.5.11 or 4.6.4 (releases at https://github.com/jupyterlab/jupyterlab/releases/tag/v4.5.11 and https://github.com/jupyterlab/jupyterlab/releases/tag/v4.6.4) and JupyterLite Core 0.8.4 or later; the fix is the upstream commits 985a3223cd77fd4f991cd90066342a90711d70f6, de324ae91346c713c4f5e5485f97b6e914e0f774, and f9de43dc565a1118120d466117f877a189a4ce90, with the primary change adding the missing end anchor to the Plural-Forms validation regex in packages/translation/src/gettext.ts. Until upgrading, treat third-party language packs as untrusted code: disable or remove non-default locale catalogues so that only the default English locale (which loads no catalogue) is used - the trade-off is loss of localized UI. If non-English translations are required, source catalogues only from vetted, integrity-checked builds and audit each catalogue's Plural-Forms header for content beyond a well-formed 'nplurals=N; plural=(...)' rule, since any trailing JavaScript after a valid rule is the exploitation signature; this manual review is error-prone and not a substitute for patching. Additionally, reduce the value of a successful injection by restricting exposure of Jupyter Server kernels, terminals, and web APIs to the JupyterLab origin, since the assessment notes that file read/modify and code execution depend on those surfaces being reachable - JupyterLite deployments already benefit from their typical absence. No public exploit code or confirmed in-the-wild exploitation was identified at time of analysis, so prioritization should follow the Medium CVSS 6.8 score and the requirement for user interaction rather than emergency response.

Affected VersionsENISA

jupyterlab 3.0.0, < 4.5.11
jupyterlite-core < 0.8.4
jupyterlab 4.6.0, < 4.6.4

Affected Packages

pypi jupyterlab fix: 4.5.11, 4.6.4
pypi jupyterlite-core fix: 0.8.4

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 2 packages in pypi

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

The flaw lives in the gettext handling of the @jupyterlab/translation package (packages/translation/src/gettext.ts), which parses the gettext Plural-Forms header from a locale's compiled JSON catalogue. Gettext plural rules are real expressions evaluated to pick a plural form, and JupyterLab implements this by constructing a function via new Function from the parsed expression. The validation regex used to gate the header was prefix-only (it ended with the character class [...] without a trailing $ anchor), so a string such as 'nplurals=2; plural=(n > 1); globalThis.__jupyterLabTranslationXss = true;' satisfies the pattern up to the closing parenthesis while the trailing attacker-controlled JavaScript is still carried into the evaluated expression. The upstream fix (commit 985a3223cd77fd4f991cd90066342a90711d70f6) adds the missing end anchor, converting the pattern to '^\s*nplurals\s*=\s*\d+\s*;\s*plural\s*=[\s\-?|&=!<>+*/%:;n0-9_()]+$', and the accompanying test asserts that a catalogue with appended JavaScript throws 'not valid' rather than setting the injected global. The root cause class is tracked as CWE-79 (improper neutralization of input during web page generation, i.e. cross-site scripting), since the injected payload executes within the JupyterLab web origin with that origin's authenticated context and can therefore reach Jupyter Server web APIs when they are exposed; JupyterLite, which typically does not expose kernels, terminals, or the Jupyter Server API from the same origin, correspondingly limits the blast radius.

Know when JavaScript gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (github) PRIMARY 6.8 MEDIUM
AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N
vuln.today AI 6.8 MEDIUM

Network-reachable but AC:H because the attacker must supply a crafted third-party locale the victim then selects (UI:R); no auth needed (PR:N); code runs in authenticated origin yielding C:H/I:H.

3.1 AV:N/AC:H/PR:N/UI:R/S:U/C:H/I:H/A:N
4.0 AV:N/AC:H/AT:N/PR:N/UI:A/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N
Red Hat 6.8 MEDIUM

Primary rating from Vendor (github).

CVSS VectorVendor: github

Attack Vector
Network
Attack Complexity
High
Privileges Required
None
User Interaction
Required
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
None

Lifecycle Timeline

2
Patch available
Sep 29, 2026 - 20:04 EUVD
CVE Published
Sep 29, 2026 - 19:17 cve.org
MEDIUM 6.8

DescriptionCVE.org

JupyterLab is an extensible environment for interactive and reproducible computing, based on the Jupyter Notebook Architecture. From JupyterLab 3.0.0 until 4.5.11 and 4.6.4, and in JupyterLite Core 0.8.3 and earlier, the Plural-Forms header in a selected third-party language pack can append JavaScript after a valid plural rule because prefix-only regular-expression validation accepts a matching prefix without requiring the entire header to match. JupyterLab passes the accepted expression to new Function, so loading the catalogue and translating a plural string executes the appended code in the authenticated JupyterLab origin. Where Jupyter Server kernels, terminals, and APIs are exposed, the code can use authenticated server APIs to read or modify files and run code. Impact is much more limited in JupyterLite because it typically lacks most exposed Jupyter Server surfaces. The default English locale is unaffected because it does not load a translation catalogue. This issue is fixed in JupyterLab 4.5.11 and 4.6.4 and JupyterLite Core 0.8.4.

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 5 pypi packages depend on jupyterlab (2 direct, 3 indirect)

Ecosystem-wide dependent count for version 4.6.0.

Threat Intelligence Overview

EPSS Score
0.3%
Top 83% exploitable
Prevalence
High
JupyterLab is a dominant interactive notebook environment across data science and ML teams
Threat Intel
1
1 sources
Data Quality
5 sources
Confidence: Medium
EUVD NVD CVE.org EPSS Vulnrichment GHSA Vendor GitHub

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity MEDIUM
CISA KEV No
Public POC No
EPSS 0.3%
Patch available Yes
Active threat No
Deciding rule
MEDIUM severity (CVSS 4.0-6.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Scheduled
Exploitation
None
System Exposure· derived
Open
Automatable
No
Human Impact· derived
High
Technical Impact
Total

Priority Score

34
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +34
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Cross-Site Scripting occurs when an application accepts untrusted data and sends it to a web browser without proper validation or encoding.

CVE-2026-102827 CRITICAL POC
9.8 Sep 29

Command injection in simple-git, the Node.js library for running git commands and published on npm, affects all releases

CVE-2026-77615 HIGH POC
8.7 Sep 17

Stored DOM-based cross-site scripting in Paella Player's closed-caption rendering path (paella-core before 2.12.11) allo

CVE-2026-92776 HIGH POC
8.6 Sep 16

Authorization bypass in Wiki.js through 2.5.314 allows an authenticated user who has been granted access to at least one

CVE-2026-102826 HIGH POC
8.1 Sep 29

Untrusted git configuration includes reachable through simple-git before 4.0.0 let an attacker execute arbitrary command

CVE-2026-85715 HIGH POC
7.5 Sep 17

Improper memory allocation control in ExifReader before 4.41.1 allows remote attackers to exhaust heap memory and termin

CVE-2026-102278 HIGH POC
7.5 Sep 28

Deeply nested brace patterns cause unbounded recursion in the npm brace-expansion library, exhausting the native stack a

CVE-2026-102276 HIGH POC
7.5 Sep 28

Stack exhaustion in the npm library brace-expansion (all versions prior to 1.1.19, 2.1.5, 3.0.7, and 5.0.10) lets a craf

CVE-2026-92775 HIGH POC
7.1 Sep 16

Server-side request forgery in Wiki.js through 2.5.314 lets an authenticated user who holds page-editing permissions for

CVE-2026-101910 MEDIUM POC
6.9 Sep 28

The JavaScript library ip-address (npm) fails to treat the NAT64 local-use prefix 64:ff9b:1::/48 as private, so applicat

CVE-2026-101914 MEDIUM POC
6.5 Sep 28

Authorization bypass in the @grpc/grpc-js-xds package (the xDS/RBAC extension for @grpc/grpc-js) lets a request for one

CVE-2026-101912 MEDIUM POC
6.3 Sep 28

Cross-family subnet comparisons in the ip-address npm library (all versions before 10.7.1) can cause isInSubnet and isHo

CVE-2026-101911 MEDIUM POC
6.3 Sep 28

Denial of service in the ip-address JavaScript/npm library (all versions prior to 10.7.1) lets remote attackers stall or

Vendor StatusVendor

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy