mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
AAE-42904 Escape html in evaluated fields and variables for rich-text display widget (#11718)
This commit is contained in:
+2
-2
@@ -68,8 +68,8 @@ export abstract class BaseDisplayTextWidgetComponent extends WidgetComponent imp
|
||||
protected abstract reevaluateExpressions(): void;
|
||||
private readonly destroyRef = inject(DestroyRef);
|
||||
|
||||
protected resolveExpressions(text: string): string {
|
||||
return this.formExpressionService.resolveExpressions(this.field.form, text);
|
||||
protected resolveExpressions(text: string, escapeHtml?: boolean): string {
|
||||
return this.formExpressionService.resolveExpressions(this.field.form, text, escapeHtml);
|
||||
}
|
||||
|
||||
private applyExpressions() {
|
||||
|
||||
@@ -268,6 +268,34 @@ describe('FormExpressionService', () => {
|
||||
|
||||
expect(result).toBe('true');
|
||||
});
|
||||
|
||||
describe('when escapeHtml is true', () => {
|
||||
let getFieldSpy: jasmine.Spy;
|
||||
|
||||
beforeEach(() => {
|
||||
getFieldSpy = spyOn(formModel, 'getFieldById');
|
||||
});
|
||||
|
||||
it('should escape ampersands in resolved field values', () => {
|
||||
getFieldSpy.and.returnValue({ id: 'f', value: 'a & b' } as any);
|
||||
expect(service.resolveExpressions(formModel, '${field.f}', true)).toBe('a & b');
|
||||
});
|
||||
|
||||
it('should escape all HTML special characters in an XSS-like payload', () => {
|
||||
getFieldSpy.and.returnValue({ id: 'f', value: `<img src="x" onerror='alert(1)'>` } as any);
|
||||
expect(service.resolveExpressions(formModel, '${field.f}', true)).toBe('<img src="x" onerror='alert(1)'>');
|
||||
});
|
||||
|
||||
it('should not escape characters when escapeHtml is false', () => {
|
||||
getFieldSpy.and.returnValue({ id: 'f', value: '<b>bold</b>' } as any);
|
||||
expect(service.resolveExpressions(formModel, '${field.f}', false)).toBe('<b>bold</b>');
|
||||
});
|
||||
|
||||
it('should not escape characters when escapeHtml is omitted', () => {
|
||||
getFieldSpy.and.returnValue({ id: 'f', value: '<b>bold</b>' } as any);
|
||||
expect(service.resolveExpressions(formModel, '${field.f}')).toBe('<b>bold</b>');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getFieldDependencies', () => {
|
||||
|
||||
@@ -27,7 +27,7 @@ export class FormExpressionService {
|
||||
private readonly VARIABLE_PREFIX = 'variable.';
|
||||
private readonly VARIABLES_REGEX = /(?:field|variable)\.[a-zA-Z_$][a-zA-Z0-9_$]*/g;
|
||||
|
||||
resolveExpressions(form: FormModel, formField: string): string {
|
||||
resolveExpressions(form: FormModel, formField: string, escapeHtml?: boolean): string {
|
||||
let result = formField || '';
|
||||
|
||||
const matches = result.match(this.GLOBAL_EXPRESSION_REGEX);
|
||||
@@ -43,6 +43,19 @@ export class FormExpressionService {
|
||||
} else if (typeof expressionResult !== 'string') {
|
||||
expressionResult = JSON.stringify(expressionResult);
|
||||
}
|
||||
if (escapeHtml) {
|
||||
expressionResult = expressionResult
|
||||
.split('&')
|
||||
.join('&')
|
||||
.split('<')
|
||||
.join('<')
|
||||
.split('>')
|
||||
.join('>')
|
||||
.split('"')
|
||||
.join('"')
|
||||
.split("'")
|
||||
.join(''');
|
||||
}
|
||||
result = result.replace(match, expressionResult);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user