diff --git a/packages/@n8n/api-types/src/dto/api-keys/update-api-key-request.dto.ts b/packages/@n8n/api-types/src/dto/api-keys/update-api-key-request.dto.ts
index b123b718ed1..31b52659564 100644
--- a/packages/@n8n/api-types/src/dto/api-keys/update-api-key-request.dto.ts
+++ b/packages/@n8n/api-types/src/dto/api-keys/update-api-key-request.dto.ts
@@ -1,9 +1,15 @@
+import xss from 'xss';
import { z } from 'zod';
import { scopesSchema } from '../../schemas/scopes.schema';
-import { xssCheck } from '../../utils/xss-check';
import { Z } from '../../zod-class';
+const xssCheck = (value: string) =>
+ value ===
+ xss(value, {
+ whiteList: {},
+ });
+
export class UpdateApiKeyRequestDto extends Z.class({
label: z.string().max(50).min(1).refine(xssCheck),
scopes: scopesSchema,
diff --git a/packages/@n8n/api-types/src/dto/user/user-update-request.dto.ts b/packages/@n8n/api-types/src/dto/user/user-update-request.dto.ts
index 776dac21563..abc044a8f42 100644
--- a/packages/@n8n/api-types/src/dto/user/user-update-request.dto.ts
+++ b/packages/@n8n/api-types/src/dto/user/user-update-request.dto.ts
@@ -1,8 +1,14 @@
+import xss from 'xss';
import { z } from 'zod';
-import { xssCheck } from '../../utils/xss-check';
import { Z } from '../../zod-class';
+const xssCheck = (value: string) =>
+ value ===
+ xss(value, {
+ whiteList: {}, // no tags are allowed
+ });
+
const URL_REGEX = /^(https?:\/\/|www\.)|(\.[\p{L}\d-]+)/iu;
const urlCheck = (value: string) => !URL_REGEX.test(value);
diff --git a/packages/@n8n/api-types/src/dto/workflows/__tests__/create-workflow.dto.test.ts b/packages/@n8n/api-types/src/dto/workflows/__tests__/create-workflow.dto.test.ts
index afce03131d3..eef51e3377d 100644
--- a/packages/@n8n/api-types/src/dto/workflows/__tests__/create-workflow.dto.test.ts
+++ b/packages/@n8n/api-types/src/dto/workflows/__tests__/create-workflow.dto.test.ts
@@ -126,21 +126,6 @@ describe('CreateWorkflowDto', () => {
request: { name: 'a'.repeat(129), nodes: [], connections: {} },
expectedErrorPath: ['name'],
},
- {
- name: 'name containing a script tag',
- request: { name: '', nodes: [], connections: {} },
- expectedErrorPath: ['name'],
- },
- {
- name: 'name containing an img onerror payload',
- request: { name: '
', nodes: [], connections: {} },
- expectedErrorPath: ['name'],
- },
- {
- name: 'name containing inline HTML markup',
- request: { name: 'Report bold', nodes: [], connections: {} },
- expectedErrorPath: ['name'],
- },
{
name: 'missing nodes',
request: { name: 'Test', connections: {} },
diff --git a/packages/@n8n/api-types/src/dto/workflows/__tests__/update-workflow.dto.test.ts b/packages/@n8n/api-types/src/dto/workflows/__tests__/update-workflow.dto.test.ts
index 9d5b81d2487..5586a708fc8 100644
--- a/packages/@n8n/api-types/src/dto/workflows/__tests__/update-workflow.dto.test.ts
+++ b/packages/@n8n/api-types/src/dto/workflows/__tests__/update-workflow.dto.test.ts
@@ -98,21 +98,6 @@ describe('UpdateWorkflowDto', () => {
request: { name: 'a'.repeat(129) },
expectedErrorPath: ['name'],
},
- {
- name: 'name containing a script tag',
- request: { name: '' },
- expectedErrorPath: ['name'],
- },
- {
- name: 'name containing an img onerror payload',
- request: { name: '
' },
- expectedErrorPath: ['name'],
- },
- {
- name: 'name containing inline HTML markup',
- request: { name: 'Report bold' },
- expectedErrorPath: ['name'],
- },
{
name: 'invalid nodes type',
request: { nodes: 'not-an-array' },
diff --git a/packages/@n8n/api-types/src/dto/workflows/base-workflow.dto.ts b/packages/@n8n/api-types/src/dto/workflows/base-workflow.dto.ts
index ded5e9ea82b..69af6161220 100644
--- a/packages/@n8n/api-types/src/dto/workflows/base-workflow.dto.ts
+++ b/packages/@n8n/api-types/src/dto/workflows/base-workflow.dto.ts
@@ -1,8 +1,6 @@
import type { IPinData, IConnections, IDataObject, INode, IWorkflowSettings } from 'n8n-workflow';
import { z } from 'zod';
-import { xssCheck } from '../../utils/xss-check';
-
export const WORKFLOW_NAME_MAX_LENGTH = 128;
/** Maximum allowed size for pinned data in bytes (12 MB) */
@@ -19,8 +17,7 @@ export const workflowNameSchema = z
.min(1, { message: 'Workflow name is required' })
.max(WORKFLOW_NAME_MAX_LENGTH, {
message: `Workflow name must be ${WORKFLOW_NAME_MAX_LENGTH} characters or less`,
- })
- .refine(xssCheck, { message: 'Potentially malicious string' });
+ });
export const workflowDescriptionSchema = z.string().nullable();
diff --git a/packages/@n8n/api-types/src/index.ts b/packages/@n8n/api-types/src/index.ts
index 68f248576bf..afaeb273a7b 100644
--- a/packages/@n8n/api-types/src/index.ts
+++ b/packages/@n8n/api-types/src/index.ts
@@ -457,7 +457,6 @@ export {
} from './schemas/eval-insights.schema';
export { ALLOWED_DOMAINS, isAllowedDomain } from './utils/allowed-domains';
-export { xssCheck } from './utils/xss-check';
export type { PublishTimelineEvent } from './schemas/workflow-publish-timeline.schema';
export {
diff --git a/packages/@n8n/api-types/src/schemas/__tests__/data-table.schema.test.ts b/packages/@n8n/api-types/src/schemas/__tests__/data-table.schema.test.ts
deleted file mode 100644
index b08af46bf85..00000000000
--- a/packages/@n8n/api-types/src/schemas/__tests__/data-table.schema.test.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { dataTableNameSchema } from '../data-table.schema';
-
-describe('dataTableNameSchema', () => {
- describe('Valid names', () => {
- test.each([
- 'Customers',
- 'Customer orders 2024',
- 'orders-q1',
- "Q1 'Quarterly' Report",
- 'orders & invoices',
- 'a',
- ])('accepts %p', (value) => {
- expect(dataTableNameSchema.safeParse(value).success).toBe(true);
- });
-
- test('trims surrounding whitespace', () => {
- const result = dataTableNameSchema.safeParse(' Customers ');
- expect(result.success).toBe(true);
- expect(result.data).toBe('Customers');
- });
- });
-
- describe('Invalid names', () => {
- test.each([
- ['empty string', ''],
- ['only whitespace', ' '],
- ['too long', 'a'.repeat(129)],
- ['contains a script tag', ''],
- ['contains an img onerror payload', '
'],
- ['contains inline HTML markup', 'Customers bold'],
- ['contains an svg onload payload', '