fix: Replace jsdom for detecting html with more lightweight lib (no-changelog) (#18188)

This commit is contained in:
Michael Kret
2025-08-11 17:03:41 +03:00
committed by GitHub
parent 660f2ff09b
commit 58df26c70b
4 changed files with 52 additions and 16 deletions

View File

@@ -55,10 +55,10 @@
"fast-glob": "catalog:",
"file-type": "16.5.4",
"form-data": "catalog:",
"htmlparser2": "^10.0.0",
"http-proxy-agent": "catalog:",
"https-proxy-agent": "catalog:",
"iconv-lite": "catalog:",
"jsdom": "23.0.1",
"jsonwebtoken": "catalog:",
"lodash": "catalog:",
"luxon": "catalog:",

View File

@@ -6,6 +6,7 @@ import { Readable } from 'stream';
import {
bufferEscapeHtml,
createHtmlSandboxTransformStream,
hasHtml,
isHtmlRenderedContentType,
sandboxHtmlResponse,
} from '../html-sandbox';
@@ -373,3 +374,21 @@ describe('sandboxHtmlResponse > sandboxing disabled', () => {
expect(sandboxHtmlResponse(data)).toEqual(data);
});
});
describe('hasHtml', () => {
test('returns true for valid HTML', () => {
expect(hasHtml('<p>Hello</p>')).toBe(true);
});
test('returns true for malformed but still HTML-like content', () => {
expect(hasHtml('<div><span>Test')).toBe(true);
});
test('returns false for plain text', () => {
expect(hasHtml('Just a string')).toBe(false);
});
test('returns false for empty string', () => {
expect(hasHtml('')).toBe(false);
});
});

View File

@@ -1,6 +1,6 @@
import { SecurityConfig } from '@n8n/config';
import { Container } from '@n8n/di';
import { JSDOM } from 'jsdom';
import { ElementType, parseDocument } from 'htmlparser2';
import type { TransformCallback } from 'stream';
import { Transform } from 'stream';
@@ -13,10 +13,8 @@ export const isIframeSandboxDisabled = () => {
*/
export const hasHtml = (str: string) => {
try {
const dom = new JSDOM(str);
return (
dom.window.document.body.children.length > 0 || dom.window.document.head.children.length > 0
);
const doc = parseDocument(str);
return doc.children.some((node) => node.type === ElementType.Tag);
} catch {
return false;
}

39
pnpm-lock.yaml generated
View File

@@ -1810,6 +1810,9 @@ importers:
form-data:
specifier: 4.0.4
version: 4.0.4
htmlparser2:
specifier: ^10.0.0
version: 10.0.0
http-proxy-agent:
specifier: 'catalog:'
version: 7.0.2
@@ -1819,9 +1822,6 @@ importers:
iconv-lite:
specifier: 'catalog:'
version: 0.6.3
jsdom:
specifier: 23.0.1
version: 23.0.1
jsonwebtoken:
specifier: 'catalog:'
version: 9.0.2
@@ -9778,6 +9778,9 @@ packages:
domutils@3.1.0:
resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==}
domutils@3.2.2:
resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==}
dot-case@3.0.4:
resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==}
@@ -9898,14 +9901,14 @@ packages:
resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==}
engines: {node: '>=0.12'}
entities@4.4.0:
resolution: {integrity: sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==}
engines: {node: '>=0.12'}
entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
entities@6.0.1:
resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==}
engines: {node: '>=0.12'}
env-paths@2.2.1:
resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
engines: {node: '>=6'}
@@ -11014,6 +11017,9 @@ packages:
resolution: {integrity: sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==}
engines: {node: '>=14'}
htmlparser2@10.0.0:
resolution: {integrity: sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==}
htmlparser2@5.0.1:
resolution: {integrity: sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==}
@@ -24938,7 +24944,7 @@ snapshots:
dependencies:
domelementtype: 2.3.0
domhandler: 5.0.3
entities: 4.4.0
entities: 4.5.0
domain-browser@4.22.0: {}
@@ -24974,6 +24980,12 @@ snapshots:
domelementtype: 2.3.0
domhandler: 5.0.3
domutils@3.2.2:
dependencies:
dom-serializer: 2.0.0
domelementtype: 2.3.0
domhandler: 5.0.3
dot-case@3.0.4:
dependencies:
no-case: 3.0.4
@@ -25110,10 +25122,10 @@ snapshots:
entities@3.0.1: {}
entities@4.4.0: {}
entities@4.5.0: {}
entities@6.0.1: {}
env-paths@2.2.1: {}
epub2@3.0.2(ts-toolbelt@9.6.0):
@@ -26626,6 +26638,13 @@ snapshots:
htmlparser2: 8.0.2
selderee: 0.11.0
htmlparser2@10.0.0:
dependencies:
domelementtype: 2.3.0
domhandler: 5.0.3
domutils: 3.2.2
entities: 6.0.1
htmlparser2@5.0.1:
dependencies:
domelementtype: 2.3.0