mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
fix: Sanitise IdP provided information in SAML test pages
This commit is contained in:
parent
94cfb3727c
commit
b4cf627cd3
|
@ -0,0 +1,33 @@
|
||||||
|
import { getSamlConnectionTestFailedView } from '../saml-connection-test-failed';
|
||||||
|
|
||||||
|
const basicXssPayload = '<script>alert("1");</script>';
|
||||||
|
const basicXssMitigated = '<script>alert("1");</script>';
|
||||||
|
|
||||||
|
describe('SAML Connection Test Failed', () => {
|
||||||
|
test('should not allow XSS via error message', () => {
|
||||||
|
const result = getSamlConnectionTestFailedView('Test ' + basicXssPayload);
|
||||||
|
expect(result).not.toMatch(basicXssPayload);
|
||||||
|
expect(result).toMatch(basicXssMitigated);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not allow XSS via attributes', () => {
|
||||||
|
const result = getSamlConnectionTestFailedView('', {
|
||||||
|
email: 'test@example.com',
|
||||||
|
firstName: 'Test',
|
||||||
|
lastName: 'McXss' + basicXssPayload,
|
||||||
|
userPrincipalName: 'test@example.com',
|
||||||
|
});
|
||||||
|
expect(result).not.toMatch(basicXssPayload);
|
||||||
|
expect(result).toMatch(basicXssMitigated);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should replace undefined with (n/a)', () => {
|
||||||
|
expect(
|
||||||
|
getSamlConnectionTestFailedView('', {
|
||||||
|
firstName: 'No',
|
||||||
|
lastName: 'Email',
|
||||||
|
userPrincipalName: 'test@example.com',
|
||||||
|
}),
|
||||||
|
).toMatch('<strong>Email:</strong> (n/a)');
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { getSamlConnectionTestSuccessView } from '../saml-connection-test-success';
|
||||||
|
|
||||||
|
const basicXssPayload = '<script>alert("1");</script>';
|
||||||
|
const basicXssMitigated = '<script>alert("1");</script>';
|
||||||
|
|
||||||
|
describe('SAML Connection Test Succeeded', () => {
|
||||||
|
test('should not allow XSS via attributes', () => {
|
||||||
|
const result = getSamlConnectionTestSuccessView({
|
||||||
|
email: 'test@example.com',
|
||||||
|
firstName: 'Test',
|
||||||
|
lastName: 'McXss' + basicXssPayload,
|
||||||
|
userPrincipalName: 'test@example.com',
|
||||||
|
});
|
||||||
|
expect(result).not.toMatch(basicXssPayload);
|
||||||
|
expect(result).toMatch(basicXssMitigated);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should replace undefined with (n/a)', () => {
|
||||||
|
expect(
|
||||||
|
getSamlConnectionTestSuccessView({
|
||||||
|
firstName: 'No',
|
||||||
|
lastName: 'Email',
|
||||||
|
userPrincipalName: 'test@example.com',
|
||||||
|
}),
|
||||||
|
).toMatch('<strong>Email:</strong> (n/a)');
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,10 +1,8 @@
|
||||||
|
import { compile } from 'handlebars';
|
||||||
|
|
||||||
import type { SamlUserAttributes } from '../types/saml-user-attributes';
|
import type { SamlUserAttributes } from '../types/saml-user-attributes';
|
||||||
|
|
||||||
export function getSamlConnectionTestFailedView(
|
const failedTemplate = compile<{ message?: string; attributes?: SamlUserAttributes }>(`
|
||||||
message: string,
|
|
||||||
attributes?: SamlUserAttributes,
|
|
||||||
): string {
|
|
||||||
return `
|
|
||||||
<http>
|
<http>
|
||||||
<head>
|
<head>
|
||||||
<title>n8n - SAML Connection Test Result</title>
|
<title>n8n - SAML Connection Test Result</title>
|
||||||
|
@ -20,23 +18,34 @@ export function getSamlConnectionTestFailedView(
|
||||||
<body>
|
<body>
|
||||||
<div style="text-align:center">
|
<div style="text-align:center">
|
||||||
<h1>SAML Connection Test failed</h1>
|
<h1>SAML Connection Test failed</h1>
|
||||||
<h2>${message ?? 'A common issue could be that no email attribute is set'}</h2>
|
<h2>{{message}}</h2>
|
||||||
<button onclick="window.close()">You can close this window now</button>
|
<button onclick="window.close()">You can close this window now</button>
|
||||||
<p></p>
|
<p></p>
|
||||||
${
|
{{#with attributes}}
|
||||||
attributes
|
<h2>Here are the attributes returned by your SAML IdP:</h2>
|
||||||
? `
|
<ul>
|
||||||
<h2>Here are the attributes returned by your SAML IdP:</h2>
|
<li><strong>Email:</strong> {{email}}</li>
|
||||||
<ul>
|
<li><strong>First Name:</strong> {{firstName}}</li>
|
||||||
<li><strong>Email:</strong> ${attributes?.email ?? '(n/a)'}</li>
|
<li><strong>Last Name:</strong> {{lastName}}</li>
|
||||||
<li><strong>First Name:</strong> ${attributes?.firstName ?? '(n/a)'}</li>
|
<li><strong>UPN:</strong> {{userPrincipalName}}</li>
|
||||||
<li><strong>Last Name:</strong> ${attributes?.lastName ?? '(n/a)'}</li>
|
{{/with}}
|
||||||
<li><strong>UPN:</strong> ${attributes?.userPrincipalName ?? '(n/a)'}</li>
|
</ul>
|
||||||
</ul>`
|
|
||||||
: ''
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</http>
|
</http>
|
||||||
`;
|
`);
|
||||||
|
|
||||||
|
export function getSamlConnectionTestFailedView(
|
||||||
|
message?: string,
|
||||||
|
attributes?: Partial<SamlUserAttributes>,
|
||||||
|
): string {
|
||||||
|
return failedTemplate({
|
||||||
|
message: message ?? 'A common issue could be that no email attribute is set',
|
||||||
|
attributes: attributes && {
|
||||||
|
email: attributes.email ?? '(n/a)',
|
||||||
|
firstName: attributes.firstName ?? '(n/a)',
|
||||||
|
lastName: attributes.lastName ?? '(n/a)',
|
||||||
|
userPrincipalName: attributes.userPrincipalName ?? '(n/a)',
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
import { compile } from 'handlebars';
|
||||||
|
|
||||||
import type { SamlUserAttributes } from '../types/saml-user-attributes';
|
import type { SamlUserAttributes } from '../types/saml-user-attributes';
|
||||||
|
|
||||||
export function getSamlConnectionTestSuccessView(attributes: SamlUserAttributes): string {
|
const successTemplate = compile<SamlUserAttributes>(`
|
||||||
return `
|
|
||||||
<http>
|
<http>
|
||||||
<head>
|
<head>
|
||||||
<title>n8n - SAML Connection Test Result</title>
|
<title>n8n - SAML Connection Test Result</title>
|
||||||
|
@ -21,13 +22,21 @@ export function getSamlConnectionTestSuccessView(attributes: SamlUserAttributes)
|
||||||
<p></p>
|
<p></p>
|
||||||
<h2>Here are the attributes returned by your SAML IdP:</h2>
|
<h2>Here are the attributes returned by your SAML IdP:</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Email:</strong> ${attributes.email ?? '(n/a)'}</li>
|
<li><strong>Email:</strong> {{email}}</li>
|
||||||
<li><strong>First Name:</strong> ${attributes.firstName ?? '(n/a)'}</li>
|
<li><strong>First Name:</strong> {{firstName}}</li>
|
||||||
<li><strong>Last Name:</strong> ${attributes.lastName ?? '(n/a)'}</li>
|
<li><strong>Last Name:</strong> {{lastName}}</li>
|
||||||
<li><strong>UPN:</strong> ${attributes.userPrincipalName ?? '(n/a)'}</li>
|
<li><strong>UPN:</strong> {{userPrincipalName}}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</http>
|
</http>
|
||||||
`;
|
`);
|
||||||
|
|
||||||
|
export function getSamlConnectionTestSuccessView(attributes: Partial<SamlUserAttributes>): string {
|
||||||
|
return successTemplate({
|
||||||
|
email: attributes.email ?? '(n/a)',
|
||||||
|
firstName: attributes.firstName ?? '(n/a)',
|
||||||
|
lastName: attributes.lastName ?? '(n/a)',
|
||||||
|
userPrincipalName: attributes.userPrincipalName ?? '(n/a)',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue