Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

prosemirror-model

Package Overview
Dependencies
Maintainers
0
Versions
85
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

prosemirror-model - npm Package Compare versions

Comparing version 1.22.0 to 1.22.1

6

CHANGELOG.md

@@ -0,1 +1,7 @@

## 1.22.1 (2024-07-14)
### Bug fixes
Add code to `DOMSerializer` that rejects DOM output specs when they originate from attribute values, to protect against XSS attacks that use corrupt attribute input.
## 1.22.0 (2024-07-14)

@@ -2,0 +8,0 @@

2

package.json
{
"name": "prosemirror-model",
"version": "1.22.0",
"version": "1.22.1",
"description": "ProseMirror's document model",

@@ -5,0 +5,0 @@ "type": "module",

@@ -79,3 +79,3 @@ import {Fragment} from "./fragment"

let {dom, contentDOM} =
DOMSerializer.renderSpec(doc(options), this.nodes[node.type.name](node))
renderSpec(doc(options), this.nodes[node.type.name](node), null, node.attrs)
if (contentDOM) {

@@ -109,3 +109,3 @@ if (node.isLeaf)

let toDOM = this.marks[mark.type.name]
return toDOM && DOMSerializer.renderSpec(doc(options), toDOM(mark, inline))
return toDOM && renderSpec(doc(options), toDOM(mark, inline), null, mark.attrs)
}

@@ -120,40 +120,3 @@

} {
if (typeof structure == "string")
return {dom: doc.createTextNode(structure)}
if ((structure as DOMNode).nodeType != null)
return {dom: structure as DOMNode}
if ((structure as any).dom && (structure as any).dom.nodeType != null)
return structure as {dom: DOMNode, contentDOM?: HTMLElement}
let tagName = (structure as [string])[0], space = tagName.indexOf(" ")
if (space > 0) {
xmlNS = tagName.slice(0, space)
tagName = tagName.slice(space + 1)
}
let contentDOM: HTMLElement | undefined
let dom = (xmlNS ? doc.createElementNS(xmlNS, tagName) : doc.createElement(tagName)) as HTMLElement
let attrs = (structure as any)[1], start = 1
if (attrs && typeof attrs == "object" && attrs.nodeType == null && !Array.isArray(attrs)) {
start = 2
for (let name in attrs) if (attrs[name] != null) {
let space = name.indexOf(" ")
if (space > 0) dom.setAttributeNS(name.slice(0, space), name.slice(space + 1), attrs[name])
else dom.setAttribute(name, attrs[name])
}
}
for (let i = start; i < (structure as readonly any[]).length; i++) {
let child = (structure as any)[i] as DOMOutputSpec | 0
if (child === 0) {
if (i < (structure as readonly any[]).length - 1 || i > start)
throw new RangeError("Content hole must be the only child of its parent node")
return {dom, contentDOM: dom}
} else {
let {dom: inner, contentDOM: innerContent} = DOMSerializer.renderSpec(doc, child, xmlNS)
dom.appendChild(inner)
if (innerContent) {
if (contentDOM) throw new RangeError("Multiple content holes")
contentDOM = innerContent as HTMLElement
}
}
}
return {dom, contentDOM}
return renderSpec(doc, structure, xmlNS)
}

@@ -194,1 +157,80 @@

}
const suspiciousAttributeCache = new WeakMap<any, readonly any[] | null>()
function suspiciousAttributes(attrs: {[name: string]: any}): readonly any[] | null {
let value = suspiciousAttributeCache.get(attrs)
if (value === undefined)
suspiciousAttributeCache.set(attrs, value = suspiciousAttributesInner(attrs))
return value
}
function suspiciousAttributesInner(attrs: {[name: string]: any}): readonly any[] | null {
let result: any[] | null = null
function scan(value: any) {
if (value && typeof value == "object") {
if (Array.isArray(value)) {
if (typeof value[0] == "string") {
if (!result) result = []
result.push(value)
} else {
for (let i = 0; i < value.length; i++) scan(value[i])
}
} else {
for (let prop in value) scan(value[prop])
}
}
}
scan(attrs)
return result
}
function renderSpec(doc: Document, structure: DOMOutputSpec, xmlNS: string | null,
blockArraysIn: {[name: string]: any}): {
dom: DOMNode,
contentDOM?: HTMLElement
} {
if (typeof structure == "string")
return {dom: doc.createTextNode(structure)}
if ((structure as DOMNode).nodeType != null)
return {dom: structure as DOMNode}
if ((structure as any).dom && (structure as any).dom.nodeType != null)
return structure as {dom: DOMNode, contentDOM?: HTMLElement}
let tagName = (structure as [string])[0], suspicious
if (typeof tagName != "string") throw new RangeError("Invalid array passed to renderSpec")
if (blockArraysIn && (suspicious = suspiciousAttributes(blockArraysIn)) &&
suspicious.indexOf(structure) > -1)
throw new RangeError("Using an array from an attribute object as a DOM spec. This may be an attempted cross site scripting attack.")
let space = tagName.indexOf(" ")
if (space > 0) {
xmlNS = tagName.slice(0, space)
tagName = tagName.slice(space + 1)
}
let contentDOM: HTMLElement | undefined
let dom = (xmlNS ? doc.createElementNS(xmlNS, tagName) : doc.createElement(tagName)) as HTMLElement
let attrs = (structure as any)[1], start = 1
if (attrs && typeof attrs == "object" && attrs.nodeType == null && !Array.isArray(attrs)) {
start = 2
for (let name in attrs) if (attrs[name] != null) {
let space = name.indexOf(" ")
if (space > 0) dom.setAttributeNS(name.slice(0, space), name.slice(space + 1), attrs[name])
else dom.setAttribute(name, attrs[name])
}
}
for (let i = start; i < (structure as readonly any[]).length; i++) {
let child = (structure as any)[i] as DOMOutputSpec | 0
if (child === 0) {
if (i < (structure as readonly any[]).length - 1 || i > start)
throw new RangeError("Content hole must be the only child of its parent node")
return {dom, contentDOM: dom}
} else {
let {dom: inner, contentDOM: innerContent} = renderSpec(doc, child, xmlNS, blockArraysIn)
dom.appendChild(inner)
if (innerContent) {
if (contentDOM) throw new RangeError("Multiple content holes")
contentDOM = innerContent as HTMLElement
}
}
}
return {dom, contentDOM}
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc