{"id":"GHSA-c75x-9x9h-28rm","summary":"Highcharts Dashboards / Grid Pro: `DataTable.setCell` and column writers treat `__proto__` as an existing column.","details":"### Impact\nWhen a single cell value is written to a data table, the column id is used as a key on the table's column collection without filtering, so a column id of `__proto__` resolves to `Object.prototype`, is taken for an existing column, and the write lands at the row index on `Object.prototype`; a column id of `constructor` writes onto the `Object` constructor in the same way. In Dashboards releases that still supported column aliases, the id is first resolved through the alias map, so a literal `__proto__` id is redirected harmlessly there, while an alias whose target is `__proto__`, which the connector's data table options accept, reaches the same write. An attacker who controls the column id can thereby set integer-keyed properties on `Object.prototype`, one per row index, holding the written value; named properties cannot be reached through these paths, because the row index is a number. The integer keys still affect every object in the page: reading an out-of-range index on any array or plain object returns the injected value, and `for...in` over any object yields the injected keys, so unrelated code can take branches it should not using attacker-supplied data, and rendering can fail as a side effect. In Dashboards the write is reached through the Highcharts component's connector write-back, which is enabled by default through `allowConnectorUpdate` and takes the column id from the component's `columnAssignment`, or in the earliest releases from the series name, when a point is updated; in Grid Pro it is reached through cell editing in earlier releases and remains reachable through the public `DataTable` API. Exploitation requires that untrusted data reach the board or Grid configuration and that a point be updated or a cell edited, or that the application write a cell with an untrusted column id.\n\nConsequences beyond disruption depend on the consuming application.\n\n### Workarounds\nTwo measures are needed. The first closes the paths that reach `Object.prototype`; the second covers table construction, which cannot be patched from outside the library.\n\n#### 1. Strip unsafe keys from untrusted column data\n\nApply this wherever column data enters your application, before it is handed to a grid, board or `DataTable`. This is the only measure that covers the `DataTable` constructor.\n\n```js\nfunction stripUnsafeColumnIds(columns) {\n    for (const key of ['__proto__', 'constructor']) {\n        if (Object.prototype.hasOwnProperty.call(columns, key)) {\n            delete columns[key];\n        }\n    }\n\n    return columns;\n}\n\nGrid.grid('container', {\n    data: { columns: stripUnsafeColumnIds(untrustedColumns) }\n});\n```\n\n#### 2. Patch the DataTable methods\n\nNeeded if your application passes column ids that originate from untrusted input to `setCell`, `changeColumnId` or `setColumns`. Run it once at startup.\n\n```js\n{\n    const { DataTable } = Grid; // Or Dashboards\n\n    if (!DataTable) {\n        throw new Error('Patch loaded before Grid');\n    }\n\n    const unsafe = (id) =\u003e id === '__proto__' || id === 'constructor';\n\n    const setCell = DataTable.prototype.setCell;\n    DataTable.prototype.setCell = function (columnId, ...rest) {\n        if (unsafe(columnId)) {\n            return;\n        }\n        return setCell.call(this, columnId, ...rest);\n    };\n\n    const changeColumnId = DataTable.prototype.changeColumnId;\n    DataTable.prototype.changeColumnId = function (columnId, newColumnId) {\n        if (unsafe(columnId) || unsafe(newColumnId)) {\n            return false;\n        }\n        return changeColumnId.call(this, columnId, newColumnId);\n    };\n\n    const setColumns = DataTable.prototype.setColumns;\n    DataTable.prototype.setColumns = function (columns, ...rest) {\n        const safe = {};\n\n        for (const key of Object.keys(columns || {})) {\n            if (!unsafe(key)) {\n                safe[key] = columns[key];\n            }\n        }\n\n        return setColumns.call(this, safe, ...rest);\n    };\n}\n```\n\nFor npm, take `DataTable` from your import instead of the global — it is exported by Grid Lite, Grid Pro and Dashboards alike.\n\n### Obtaining the patched version\nThe patched releases are available from all the usual distribution channels. With npm, upgrade the affected package to the patched version listed above, for example `npm install @highcharts/dashboards@4.2.2`. If you load Highcharts Dashboards from a CDN, use a versioned URL, for example `https://code.highcharts.com/dashboards/4.2.2/dashboards.js`. For more on each installation method, see the [installation guide](https://www.highcharts.com/docs/dashboards/installation).","aliases":["CVE-2026-118247"],"modified":"2026-10-28T20:15:05.454379690Z","published":"2026-10-28T19:55:37Z","database_specific":{"github_reviewed_at":"2026-10-28T19:55:37Z","nvd_published_at":"2026-10-28T18:17:15Z","cwe_ids":["CWE-1321"],"severity":"MODERATE","github_reviewed":true},"references":[{"type":"WEB","url":"https://github.com/highcharts/highcharts/security/advisories/GHSA-c75x-9x9h-28rm"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-118247"},{"type":"WEB","url":"https://github.com/highcharts/highcharts/commit/02dd9349aeb6f4cc9c98806120d917ed316b4c74"},{"type":"PACKAGE","url":"https://github.com/highcharts/highcharts"},{"type":"WEB","url":"https://github.com/highcharts/highcharts/releases/tag/dashboards-v4.2.2"},{"type":"WEB","url":"https://github.com/highcharts/highcharts/releases/tag/grid-v3.2.0"}],"affected":[{"package":{"name":"@highcharts/dashboards","ecosystem":"npm","purl":"pkg:npm/%40highcharts/dashboards"},"ranges":[{"type":"SEMVER","events":[{"introduced":"1.0.0"},{"fixed":"4.2.2"}]}],"database_specific":{"last_known_affected_version_range":"\u003c= 4.2.1","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-c75x-9x9h-28rm/GHSA-c75x-9x9h-28rm.json"}},{"package":{"name":"@highcharts/grid-pro","ecosystem":"npm","purl":"pkg:npm/%40highcharts/grid-pro"},"ranges":[{"type":"SEMVER","events":[{"introduced":"2.0.0"},{"fixed":"3.2.0"}]}],"database_specific":{"last_known_affected_version_range":"\u003c= 3.1.0","source":"https://github.com/github/advisory-database/blob/main/advisories/github-reviewed/2026/10/GHSA-c75x-9x9h-28rm/GHSA-c75x-9x9h-28rm.json"}}],"schema_version":"1.9.2","severity":[{"type":"CVSS_V4","score":"CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:A/VC:N/VI:L/VA:H/SC:L/SI:L/SA:L"}]}