Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
groups:
compatible-updates:
update-types:
- minor
- patch
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
open-pull-requests-limit: 2
4 changes: 4 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# 安全与隐私

## 依赖维护

使用 `npm ci` 安装锁定依赖,使用 `npm audit` 复查已知告警。`pptxgenjs` 的间接依赖 `image-size` 暂时覆盖为 `2.0.4`,以修复旧解析器处理部分图片格式时的无限循环问题。升级 `pptxgenjs` 后应复核是否仍需该覆盖;当前原生 PPTX 导出由 `test/pptxBuilder.test.js` 验证。

## 后台运营权限边界

- 组织后台的 `/api/ops/recent-errors` 只返回当前组织归属的系统事件和 AI 失败记录,不返回 `organization_id === null` 的平台级全局事件。
Expand Down
122 changes: 105 additions & 17 deletions build/bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -11242,11 +11242,17 @@
*/
XMLNS: "http://www.w3.org/2000/xmlns/"
});
var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/;
var nameChar = new RegExp("[\\-\\.0-9" + nameStartChar.source.slice(1, -1) + "\\u00B7\\u0300-\\u036F\\u203F-\\u2040]");
var tagNamePattern = new RegExp("^" + nameStartChar.source + nameChar.source + "*(?::" + nameStartChar.source + nameChar.source + "*)?$");
exports2.assign = assign;
exports2.find = find2;
exports2.freeze = freeze;
exports2.MIME_TYPE = MIME_TYPE;
exports2.NAMESPACE = NAMESPACE;
exports2.nameStartChar = nameStartChar;
exports2.nameChar = nameChar;
exports2.tagNamePattern = tagNamePattern;
}
});

Expand All @@ -11256,6 +11262,7 @@
var conventions = require_conventions();
var find2 = conventions.find;
var NAMESPACE = conventions.NAMESPACE;
var tagNamePattern = conventions.tagNamePattern;
function notEmptyString(input) {
return input !== "";
}
Expand Down Expand Up @@ -11419,6 +11426,7 @@
};
_extends(LiveNodeList, NodeList);
function NamedNodeMap() {
this._nameIndex = /* @__PURE__ */ Object.create(null);
}
function _findNodeIndex(list, node) {
var i = list.length;
Expand All @@ -11428,12 +11436,22 @@
}
}
}
function _nnmIndexAdd(list, attr) {
list._nameIndex[attr.nodeName] = attr;
}
function _nnmIndexRemove(list, attr) {
if (list._nameIndex[attr.nodeName] === attr) {
delete list._nameIndex[attr.nodeName];
}
}
function _addNamedNode(el, list, newAttr, oldAttr) {
if (oldAttr) {
list[_findNodeIndex(list, oldAttr)] = newAttr;
_nnmIndexRemove(list, oldAttr);
} else {
list[list.length++] = newAttr;
}
_nnmIndexAdd(list, newAttr);
if (el) {
newAttr.ownerElement = el;
var doc = el.ownerDocument;
Expand All @@ -11451,6 +11469,7 @@
list[i] = list[++i];
}
list.length = lastIndex;
_nnmIndexRemove(list, attr);
if (el) {
var doc = el.ownerDocument;
if (doc) {
Expand Down Expand Up @@ -11479,7 +11498,7 @@
if (el && el != this._ownerElement) {
throw new DOMException(INUSE_ATTRIBUTE_ERR);
}
var oldAttr = this.getNamedItem(attr.nodeName);
var oldAttr = this._nameIndex[attr.nodeName];
_addNamedNode(this._ownerElement, this, attr, oldAttr);
return oldAttr;
},
Expand Down Expand Up @@ -11682,8 +11701,29 @@
while (child) {
var next = child.nextSibling;
if (next !== null && next.nodeType === TEXT_NODE && child.nodeType === TEXT_NODE) {
node.removeChild(next);
child.appendData(next.data);
var tail = [];
var sibling = next;
while (sibling !== null && sibling.nodeType === TEXT_NODE) {
tail.push(sibling.data);
sibling = sibling.nextSibling;
}
var removed = child.nextSibling;
while (removed !== sibling) {
var following = removed.nextSibling;
removed.parentNode = null;
removed.previousSibling = null;
removed.nextSibling = null;
removed = following;
}
child.nextSibling = sibling;
if (sibling !== null) {
sibling.previousSibling = child;
} else {
node.lastChild = child;
}
child.appendData(tail.join(""));
_onUpdateChild(node.ownerDocument, node);
child = sibling;
} else {
child = next;
}
Expand Down Expand Up @@ -12198,8 +12238,10 @@
* - it does not do any input validation on the arguments and doesn't throw "InvalidCharacterError".
*
* Note: When the resulting document is serialized with `requireWellFormed: true`, the
* serializer throws with code `INVALID_STATE_ERR` if `.data` contains `?>` (W3C DOM Parsing
* §3.2.1.7). Without that option the data is emitted verbatim.
* serializer throws with code `INVALID_STATE_ERR` if `.target` is not a valid XML `NCName`
* (a `Name` with no colon) or is an ASCII case-insensitive match for `"xml"`, or if `.data`
* contains `?>` (W3C DOM Parsing §3.2.1.7). Without that option the target and data are
* emitted verbatim.
*
* @param {string} target
* @param {string} data
Expand All @@ -12224,7 +12266,27 @@
node.specified = true;
return node;
},
/**
* Creates an EntityReference object, serialized as `&name;`.
*
* The `name` is validated against the XML `Name` production at creation time; an invalid name
* throws a `DOMException` with code `INVALID_CHARACTER_ERR`. When the resulting node is
* serialized with `requireWellFormed: true`, the serializer re-validates `nodeName` and throws
* a `DOMException` with code `INVALID_STATE_ERR` if a later `nodeName` mutation made it invalid;
* without that option the name is emitted verbatim.
*
* Note: xmldom does not expand entities — the parser resolves entity references inline and never
* constructs `EntityReference` nodes, so this method is the only producer.
*
* @param {string} name The name of the entity to reference.
* @returns {EntityReference}
* @throws {DOMException} With code `INVALID_CHARACTER_ERR` when `name` is not a valid XML `Name`.
* @see https://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-392B75AE
*/
createEntityReference: function(name) {
if (!tagNamePattern.test(name)) {
throw new DOMException(INVALID_CHARACTER_ERR, 'not a valid xml name "' + name + '"');
}
var node = new EntityReference();
node.ownerDocument = this;
node.nodeName = name;
Expand Down Expand Up @@ -12489,7 +12551,10 @@
}
return true;
}
function addSerializedAttribute(buf, qualifiedName, value) {
function addSerializedAttribute(buf, qualifiedName, value, requireWellFormed) {
if (requireWellFormed && !tagNamePattern.test(qualifiedName)) {
throw new DOMException(INVALID_STATE_ERR, 'The attribute name "' + qualifiedName + '" is not a valid XML QName');
}
buf.push(" ", qualifiedName, '="', value.replace(/[<>&"\t\n\r]/g, _xmlEncoder), '"');
}
function serializeToString(node, buf, isHTML, nodeFilter, visibleNamespaces, requireWellFormed) {
Expand Down Expand Up @@ -12547,6 +12612,9 @@
}
}
}
if (requireWellFormed && !tagNamePattern.test(prefixedNodeName)) {
throw new DOMException(INVALID_STATE_ERR, 'The element name "' + prefixedNodeName + '" is not a valid XML QName');
}
buf.push("<", prefixedNodeName);
var childNs = ns.slice();
for (var i = 0; i < len; i++) {
Expand All @@ -12562,22 +12630,22 @@
if (needNamespaceDefine(attr, html, childNs)) {
var attrPrefix = attr.prefix || "";
var uri = attr.namespaceURI;
addSerializedAttribute(buf, attrPrefix ? "xmlns:" + attrPrefix : "xmlns", uri);
addSerializedAttribute(buf, attrPrefix ? "xmlns:" + attrPrefix : "xmlns", uri, requireWellFormed);
childNs.push({ prefix: attrPrefix, namespace: uri });
}
var filteredAttr = nodeFilter ? nodeFilter(attr) : attr;
if (filteredAttr) {
if (typeof filteredAttr === "string") {
buf.push(filteredAttr);
} else {
addSerializedAttribute(buf, filteredAttr.name, filteredAttr.value);
addSerializedAttribute(buf, filteredAttr.name, filteredAttr.value, requireWellFormed);
}
}
}
if (nodeName === prefixedNodeName && needNamespaceDefine(n, html, childNs)) {
var nodePrefix = n.prefix || "";
var uri = n.namespaceURI;
addSerializedAttribute(buf, nodePrefix ? "xmlns:" + nodePrefix : "xmlns", uri);
addSerializedAttribute(buf, nodePrefix ? "xmlns:" + nodePrefix : "xmlns", uri, requireWellFormed);
childNs.push({ prefix: nodePrefix, namespace: uri });
}
var child = n.firstChild;
Expand All @@ -12604,7 +12672,7 @@
case DOCUMENT_FRAGMENT_NODE:
return { ns: ns.slice(), isHTML: html, tag: null };
case ATTRIBUTE_NODE:
addSerializedAttribute(buf, n.name, n.value);
addSerializedAttribute(buf, n.name, n.value, requireWellFormed);
return null;
case TEXT_NODE:
buf.push(n.data.replace(/[<&>]/g, _xmlEncoder));
Expand All @@ -12623,6 +12691,9 @@
return null;
case DOCUMENT_TYPE_NODE:
if (requireWellFormed) {
if (!tagNamePattern.test(n.name)) {
throw new DOMException(INVALID_STATE_ERR, 'The doctype name "' + n.name + '" is not a valid XML Name');
}
if (n.publicId && !/^("[\x20\r\na-zA-Z0-9\-()+,.\/:=?;!*#@$_%']*"|'[\x20\r\na-zA-Z0-9\-()+,.\/:=?;!*#@$_%'"]*')$/.test(n.publicId)) {
throw new DOMException(INVALID_STATE_ERR, "DocumentType publicId is not a valid PubidLiteral");
}
Expand Down Expand Up @@ -12653,12 +12724,26 @@
}
return null;
case PROCESSING_INSTRUCTION_NODE:
if (requireWellFormed && n.data.indexOf("?>") !== -1) {
throw new DOMException(INVALID_STATE_ERR, 'The ProcessingInstruction data contains "?>"');
if (requireWellFormed) {
if (!tagNamePattern.test(n.target) || n.target.indexOf(":") !== -1 || n.target.toLowerCase() === "xml") {
throw new DOMException(
INVALID_STATE_ERR,
'The processing instruction target "' + n.target + '" is not a valid XML NCName or is reserved'
);
}
if (n.data.indexOf("?>") !== -1) {
throw new DOMException(INVALID_STATE_ERR, 'The ProcessingInstruction data contains "?>"');
}
}
buf.push("<?", n.target, " ", n.data, "?>");
return null;
case ENTITY_REFERENCE_NODE:
if (requireWellFormed && !tagNamePattern.test(n.nodeName)) {
throw new DOMException(
INVALID_STATE_ERR,
'The entity reference name "' + n.nodeName + '" is not a valid XML Name'
);
}
buf.push("&", n.nodeName, ";");
return null;
//case ENTITY_NODE:
Expand Down Expand Up @@ -14948,9 +15033,7 @@
var require_sax = __commonJS({
"node_modules/@xmldom/xmldom/lib/sax.js"(exports2) {
var NAMESPACE = require_conventions().NAMESPACE;
var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/;
var nameChar = new RegExp("[\\-\\.0-9" + nameStartChar.source.slice(1, -1) + "\\u00B7\\u0300-\\u036F\\u203F-\\u2040]");
var tagNamePattern = new RegExp("^" + nameStartChar.source + nameChar.source + "*(?::" + nameStartChar.source + nameChar.source + "*)?$");
var tagNamePattern = require_conventions().tagNamePattern;
var S_TAG = 0;
var S_ATTR = 1;
var S_ATTR_SPACE = 2;
Expand Down Expand Up @@ -15045,7 +15128,7 @@
switch (source.charAt(tagStart + 1)) {
case "/":
var end = source.indexOf(">", tagStart + 3);
var tagName = source.substring(tagStart + 2, end).replace(/[ \t\n\r]+$/g, "");
var tagName = source.substring(tagStart + 2, end).replace(/^([\s\S]*?[^ \t\n\r])?[ \t\n\r]*$/, "$1");
var config = parseStack.pop();
if (end < 0) {
tagName = source.substring(tagStart + 2).replace(/[\s<].*/, "");
Expand All @@ -15055,6 +15138,8 @@
tagName = tagName.replace(/[\s<].*/, "");
errorHandler.error("end tag name: " + tagName + " maybe not complete");
end = tagStart + 1 + tagName.length;
} else if (/[ \t\n\r]/.test(tagName) && tagNamePattern.test(tagName.split(/[ \t\n\r]/)[0])) {
errorHandler.error('end tag name is followed by whitespace and trailing content: "' + tagName + '"');
}
var localNSMap = config.localNSMap;
var endMatch = config.tagName == tagName;
Expand Down Expand Up @@ -15160,6 +15245,9 @@
var s = S_TAG;
while (true) {
var c = source.charAt(p);
if (s === S_TAG && c === "<") {
throw new Error("unexpected < in tag name: " + source.slice(start, p));
}
switch (c) {
case "=":
if (s === S_ATTR) {
Expand Down Expand Up @@ -15334,7 +15422,7 @@
if (nsPrefix !== false) {
if (localNSMap == null) {
localNSMap = {};
_copy(currentNSMap, currentNSMap = {});
currentNSMap = Object.create(currentNSMap);
}
currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
a.uri = NAMESPACE.XMLNS;
Expand Down
26 changes: 7 additions & 19 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,10 @@
"mammoth": "^1.12.0",
"pg": "^8.13.1",
"pptxgenjs": "^4.0.1"
},
"overrides": {
"pptxgenjs": {
"image-size": "2.0.4"
}
}
}
Loading