diff --git a/cypress/e2e/33-settings-personal.cy.ts b/cypress/e2e/33-settings-personal.cy.ts
new file mode 100644
index 0000000000000..9257bee22d25f
--- /dev/null
+++ b/cypress/e2e/33-settings-personal.cy.ts
@@ -0,0 +1,52 @@
+import { WorkflowPage } from "../pages";
+
+const workflowPage = new WorkflowPage();
+
+const INVALID_NAMES = [
+ 'https://n8n.io',
+ 'http://n8n.io',
+ 'www.n8n.io',
+ 'n8n.io',
+ 'n8n.бг',
+ 'n8n.io/home',
+ 'n8n.io/home?send=true',
+ 'Jack',
+ '',
+];
+
+const VALID_NAMES = [
+ ['a', 'a'],
+ ['alice', 'alice'],
+ ['Robert', 'Downey Jr.'],
+ ['Mia', 'Mia-Downey'],
+ ['Mark', "O'neil"],
+ ['Thomas', 'Müler'],
+ ['ßáçøñ', 'ßáçøñ'],
+ ['أحمد', 'فلسطين'],
+ ['Милорад', 'Филиповић'],
+];
+
+describe('Personal Settings', () => {
+ it ('should allow to change first and last name', () => {
+ cy.visit('/settings/personal');
+ VALID_NAMES.forEach((name) => {
+ cy.getByTestId('personal-data-form').find('input[name="firstName"]').clear().type(name[0]);
+ cy.getByTestId('personal-data-form').find('input[name="lastName"]').clear().type(name[1]);
+ cy.getByTestId('save-settings-button').click();
+ workflowPage.getters.successToast().should('contain', 'Personal details updated');
+ workflowPage.getters.successToast().find('.el-notification__closeBtn').click();
+ });
+ });
+ it('not allow malicious values for personal data', () => {
+ cy.visit('/settings/personal');
+ INVALID_NAMES.forEach((name) => {
+ cy.getByTestId('personal-data-form').find('input[name="firstName"]').clear().type(name);
+ cy.getByTestId('personal-data-form').find('input[name="lastName"]').clear().type(name);
+ cy.getByTestId('save-settings-button').click();
+ workflowPage.getters
+ .errorToast()
+ .should('contain', 'Malicious firstName | Malicious lastName');
+ workflowPage.getters.errorToast().find('.el-notification__closeBtn').click();
+ });
+ });
+});
diff --git a/packages/cli/src/databases/utils/customValidators.ts b/packages/cli/src/databases/utils/customValidators.ts
index f84832fe5507b..8d397e982a0c3 100644
--- a/packages/cli/src/databases/utils/customValidators.ts
+++ b/packages/cli/src/databases/utils/customValidators.ts
@@ -11,7 +11,7 @@ export function NoXss() {
options: { message: `Malicious ${propertyName}` },
validator: {
validate(value: string) {
- return !/<(\s*)?(script|a|http)/.test(value);
+ return !/(^http|^www)|<(\s*)?(script|a)|(\.[\p{L}\d-]+)/u.test(value);
},
},
});
diff --git a/packages/cli/test/unit/databases/utils/customValidators.test.ts b/packages/cli/test/unit/databases/utils/customValidators.test.ts
new file mode 100644
index 0000000000000..df906b36d6a52
--- /dev/null
+++ b/packages/cli/test/unit/databases/utils/customValidators.test.ts
@@ -0,0 +1,43 @@
+import { NoXss } from '@db/utils/customValidators';
+import { validate } from 'class-validator';
+
+describe('customValidators', () => {
+ describe('NoXss', () => {
+ class Person {
+ @NoXss()
+ name: string;
+ }
+ const person = new Person();
+
+ const invalidNames = ['http://google.com', '', 'www.domain.tld'];
+
+ const validNames = [
+ 'Johann Strauß',
+ 'Вагиф Сәмәдоғлу',
+ 'René Magritte',
+ 'সুকুমার রায়',
+ 'མགོན་པོ་རྡོ་རྗེ།',
+ 'عبدالحليم حافظ',
+ ];
+
+ describe('Block XSS', () => {
+ for (const name of invalidNames) {
+ test(name, async () => {
+ person.name = name;
+ const validationErrors = await validate(person);
+ expect(validationErrors[0].property).toEqual('name');
+ expect(validationErrors[0].constraints).toEqual({ NoXss: 'Malicious name' });
+ });
+ }
+ });
+
+ describe('Allow Valid names', () => {
+ for (const name of validNames) {
+ test(name, async () => {
+ person.name = name;
+ expect(await validate(person)).toBeEmptyArray();
+ });
+ }
+ });
+ });
+});
diff --git a/packages/design-system/src/components/N8nFormBox/FormBox.vue b/packages/design-system/src/components/N8nFormBox/FormBox.vue
index 3098d53eee8ce..0c6fa4b3f9593 100644
--- a/packages/design-system/src/components/N8nFormBox/FormBox.vue
+++ b/packages/design-system/src/components/N8nFormBox/FormBox.vue
@@ -24,6 +24,7 @@
v-if="buttonText"
:label="buttonText"
:loading="buttonLoading"
+ data-test-id="form-submit-button"
size="large"
@click="onButtonClick"
/>