rimecms 0.23.9 → 0.23.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/util/string.d.ts +0 -1
- package/dist/util/string.js +77 -9
- package/package.json +2 -2
package/dist/util/string.d.ts
CHANGED
|
@@ -87,6 +87,5 @@ export declare const isValidSlug: (str: string) => boolean;
|
|
|
87
87
|
* Sanitizes user input by removing dangerous HTML tags while preserving allowed formatting tags,
|
|
88
88
|
* this doesn't encode/decode HTML entities.
|
|
89
89
|
* allowed tags : ['strong', 'b', 'em', 'i', 'u', 'br', 'a']
|
|
90
|
-
* allowedAttributes : ['href', '_target']
|
|
91
90
|
*/
|
|
92
91
|
export declare const sanitize: (value?: string) => string;
|
package/dist/util/string.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { Parser } from '@thednp/domparser';
|
|
1
2
|
import camelCase from 'camelcase';
|
|
2
|
-
|
|
3
|
+
let parser;
|
|
3
4
|
/**
|
|
4
5
|
* Capitalizes the first letter of a string.
|
|
5
6
|
*
|
|
@@ -148,11 +149,12 @@ export const isValidSlug = (str) => /^[a-zA-Z][a-zA-Z0-9_-]*$/.test(str);
|
|
|
148
149
|
* Sanitizes user input by removing dangerous HTML tags while preserving allowed formatting tags,
|
|
149
150
|
* this doesn't encode/decode HTML entities.
|
|
150
151
|
* allowed tags : ['strong', 'b', 'em', 'i', 'u', 'br', 'a']
|
|
151
|
-
* allowedAttributes : ['href', '_target']
|
|
152
152
|
*/
|
|
153
153
|
export const sanitize = (value) => {
|
|
154
154
|
if (!value)
|
|
155
155
|
return value || '';
|
|
156
|
+
if (!parser)
|
|
157
|
+
parser = Parser();
|
|
156
158
|
const decode = (value) => value
|
|
157
159
|
.replace(/&/g, '&')
|
|
158
160
|
.replace(/"/g, '"')
|
|
@@ -166,12 +168,78 @@ export const sanitize = (value) => {
|
|
|
166
168
|
while (decodedValue.match(/&|"|<|>|'|'|&/)) {
|
|
167
169
|
decodedValue = decode(decodedValue);
|
|
168
170
|
}
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
171
|
+
const { root } = parser.parseFromString(decodedValue);
|
|
172
|
+
const allowedTags = new Set(['strong', 'b', 'em', 'i', 'u', 'br', 'a']);
|
|
173
|
+
const dangerousTags = new Set(['script', 'style', 'iframe', 'object', 'embed', 'svg']);
|
|
174
|
+
const eventHandlers = /^on[a-z]+$/i;
|
|
175
|
+
const dangerousUrls = /^(javascript:|data:text\/html)/i;
|
|
176
|
+
const processNode = (node) => {
|
|
177
|
+
if (!node)
|
|
178
|
+
return '';
|
|
179
|
+
// Handle text nodes
|
|
180
|
+
if (node.nodeName === '#text') {
|
|
181
|
+
return node.nodeValue || '';
|
|
182
|
+
}
|
|
183
|
+
// Handle comment nodes - remove them
|
|
184
|
+
if (node.nodeName === '#comment') {
|
|
185
|
+
return '';
|
|
186
|
+
}
|
|
187
|
+
// Handle element nodes
|
|
188
|
+
if (node.tagName) {
|
|
189
|
+
const tagName = node.tagName.toLowerCase();
|
|
190
|
+
// Remove dangerous tags entirely (including their content)
|
|
191
|
+
if (dangerousTags.has(tagName)) {
|
|
192
|
+
return '';
|
|
193
|
+
}
|
|
194
|
+
// Process children first
|
|
195
|
+
const childContent = node.children ? node.children.map(processNode).join('') : '';
|
|
196
|
+
// If not an allowed tag, return only the child content (strip the tag)
|
|
197
|
+
if (!allowedTags.has(tagName)) {
|
|
198
|
+
return childContent;
|
|
199
|
+
}
|
|
200
|
+
// For allowed tags, filter attributes
|
|
201
|
+
const safeAttributes = [];
|
|
202
|
+
if (node.attributes) {
|
|
203
|
+
for (const [key, value] of Object.entries(node.attributes)) {
|
|
204
|
+
const attrName = key.toLowerCase();
|
|
205
|
+
const attrValue = value;
|
|
206
|
+
// Remove event handlers
|
|
207
|
+
if (eventHandlers.test(attrName)) {
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
// For 'a' tags, only allow specific attributes
|
|
211
|
+
if (tagName === 'a') {
|
|
212
|
+
if (attrName === 'href') {
|
|
213
|
+
// Remove dangerous URLs
|
|
214
|
+
if (dangerousUrls.test(attrValue)) {
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
safeAttributes.push(`${attrName}="${attrValue}"`);
|
|
218
|
+
}
|
|
219
|
+
else if (attrName === '_target') {
|
|
220
|
+
safeAttributes.push(`${attrName}="${attrValue}"`);
|
|
221
|
+
}
|
|
222
|
+
// Skip all other attributes for 'a' tags
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
// For other allowed tags, remove dangerous attributes
|
|
226
|
+
if (attrName === 'href' || attrName === 'src') {
|
|
227
|
+
if (dangerousUrls.test(attrValue)) {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
// Build the tag
|
|
234
|
+
const attributeString = safeAttributes.length > 0 ? ' ' + safeAttributes.join(' ') : '';
|
|
235
|
+
// Handle self-closing tags
|
|
236
|
+
if (tagName === 'br') {
|
|
237
|
+
return `<${tagName}${attributeString}>`;
|
|
238
|
+
}
|
|
239
|
+
return `<${tagName}${attributeString}>${childContent}</${tagName}>`;
|
|
240
|
+
}
|
|
241
|
+
return '';
|
|
242
|
+
};
|
|
243
|
+
const sanitized = root.children ? root.children.map(processNode).join('') : '';
|
|
176
244
|
return decode(sanitized);
|
|
177
245
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rimecms",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.11",
|
|
4
4
|
"homepage": "https://github.com/bienbiendev/rime",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "vite dev",
|
|
@@ -173,6 +173,7 @@
|
|
|
173
173
|
"@libsql/client": "^0.15.15",
|
|
174
174
|
"@lucide/svelte": "^0.540.0",
|
|
175
175
|
"@playwright/test": "^1.52.0",
|
|
176
|
+
"@thednp/domparser": "^0.1.6",
|
|
176
177
|
"@tiptap/core": "3.11.0",
|
|
177
178
|
"@tiptap/extension-blockquote": "3.11.0",
|
|
178
179
|
"@tiptap/extension-bold": "^3.11.0",
|
|
@@ -213,7 +214,6 @@
|
|
|
213
214
|
"polka": "^0.5.2",
|
|
214
215
|
"qs": "^6.14.0",
|
|
215
216
|
"runed": "^0.23.4",
|
|
216
|
-
"sanitize-html": "^2.17.0",
|
|
217
217
|
"sharp": "^0.34.0",
|
|
218
218
|
"sortablejs": "^1.15.6",
|
|
219
219
|
"svelte-sonner": "^1.0.5"
|