{"items":[{"id":"NVI-00014078","kind":"vulnerability","title":"Tiptap: mergeAttributes() turns an own __proto__ key into inherited executable DOM attributes","revision":1,"unknowns":["Customer inventory, deployment, reachability and exploitation have not been inspected."],"lifecycle":"active","identifiers":["GHSA-cp6q-959q-f8rh"],"plain_summary":"GitHub lists this reviewed advisory for @tiptap/core. Published version ranges and source prerequisites are shown below; this is not an inspection of a visitor’s application.","review_status":"source_listed","control_topics":[],"public_actions":[{"summary":"Identify the exact component and deployed version, examine the linked publisher’s conditions, and retain evidence of any mitigation.","source_ids":["sr-3f418453e1ee05fe678a38d49f2d2501"],"action_type":"investigate","limitations":"Confirm current vendor support, compatibility and deployment evidence. This report has not tested a fix in your system.","current_supported_target":null}],"schema_version":"1.1.0","source_metrics":[],"why_it_matters":"Published affected context helps an owner decide what evidence to gather. This report has not examined your application.","related_sources":[{"id":"sr-3f418453e1ee05fe678a38d49f2d2501","url":"https://github.com/advisories/GHSA-cp6q-959q-f8rh","basis":"vendor_advisory","notes":"GitHub Advisory Database; CC-BY-4.0. Each advisory links its original attribution. Null normalizes fields.","title":"GHSA-cp6q-959q-f8rh","publisher":"GitHub Advisory Database","observed_at":"2026-11-02T02:21:43.711Z"}],"affected_context":[{"certainty":"source_listed","source_ids":["sr-3f418453e1ee05fe678a38d49f2d2501"],"technology":"@tiptap/core","known_exclusions":[],"conditions_summary":"## Summary\n\n`@tiptap/core`'s public `mergeAttributes()` helper uses ordinary bracket assignment on keys returned by `Object.entries()`. An own `__proto__` key from JSON therefore invokes the legacy prototype setter on the fresh merged object. The function returns an object whose prototype is attacker-controlled, while `Object.keys()` and ordinary own-property checks show no attacker attributes.\n\nWhen that result is used as a ProseMirror DOMOutputSpec attribute object, `prosemirror-model`'s `DOMSerializer.renderSpec()` enumerates it with `for...in` and applies inherited values with `setAttribute()`. In a browser proof, inherited `src` and `onerror` values were copied to an `` and the error handler executed once. This is per-object prototype manipulation; the proof does not modify global `Object.prototype`.\n\n## Root cause\n\nThe affected loop is conceptually:\n\n```ts\nconst mergedAttributes = { ...items }\nfor (const [key, value] of Object.entries(item)) {\n  const exists = mergedAttributes[key]\n  // ...\n  mergedAttributes[key] = value\n}\n```\n\n`Object.entries(JSON.parse('{\"__proto__\": {...}}'))` includes `__proto__`. Reading `mergedAttributes['__proto__']` resolves the inherited `Objec","public_affected_ranges":[">= 2.0.0-alpha.0, < 3.30.4"]}],"null_published_at":"2026-11-02T10:00:37.204Z","source_updated_at":"2026-09-02T14:44:40.000Z","source_disclosed_at":"2026-09-02T14:44:39.000Z","is_synthetic_fixture":false,"null_last_reviewed_at":null,"public_change_summary":"First indexed by Null; source disclosure date is shown separately.","null_first_observed_at":"2026-11-02T02:21:43.711Z"}],"next_cursor":null,"snapshot_revision":"42594"}