diff --git a/src/modal/modal.ts b/src/modal/modal.ts index 81f4783..dc349a2 100644 --- a/src/modal/modal.ts +++ b/src/modal/modal.ts @@ -632,16 +632,22 @@ export class CaptureEyeModal extends LitElement { ); } + private isValidColor(color: string): boolean { + return CSS.supports('color', color.trim()); + } + private updateModalColor() { - // Set primary color - this.style.setProperty('--primary-color', this._color); + // Clear colors first; set only if color is valid + this.style.setProperty('--primary-color', ''); + this.style.setProperty('--hover-color', ''); - // Set hover color - this.style.setProperty('--hover-color', ''); // Clear the color - if (!this._color) { + if (!this._color || !this.isValidColor(this._color)) { return; } + // Set primary color + this.style.setProperty('--primary-color', this._color); + const ctx = document.createElement('canvas').getContext('2d'); if (!ctx) { return; diff --git a/src/test/modal_test.ts b/src/test/modal_test.ts index 29a064d..c6e1875 100644 --- a/src/test/modal_test.ts +++ b/src/test/modal_test.ts @@ -526,4 +526,62 @@ suite('capture-eye-modal', () => { buttonCr = el.shadowRoot!.querySelector('.button-content-credentials'); assert.notExists(buttonCr); }); + + suite('updateModalColor color validation', () => { + test('sets --primary-color for valid hex color', async () => { + const el = await fixture(html` + + `); + el.updateModalOptions({ nid: '1', color: '#027fe5' }); + await el.updateComplete; + assert.equal(el.style.getPropertyValue('--primary-color'), '#027fe5'); + }); + + test('sets --primary-color for valid short hex color', async () => { + const el = await fixture(html` + + `); + el.updateModalOptions({ nid: '1', color: '#fff' }); + await el.updateComplete; + assert.equal(el.style.getPropertyValue('--primary-color'), '#fff'); + }); + + test('sets --primary-color for valid named color', async () => { + const el = await fixture(html` + + `); + el.updateModalOptions({ nid: '1', color: 'red' }); + await el.updateComplete; + assert.equal(el.style.getPropertyValue('--primary-color'), 'red'); + }); + + test('does not set --primary-color for invalid color with semicolon injection', async () => { + const el = await fixture(html` + + `); + el.updateModalOptions({ nid: '1', color: 'red; --injected: value' }); + await el.updateComplete; + assert.equal(el.style.getPropertyValue('--primary-color'), ''); + }); + + test('does not set --primary-color for arbitrary string', async () => { + const el = await fixture(html` + + `); + el.updateModalOptions({ nid: '1', color: 'not-a-color' }); + await el.updateComplete; + assert.equal(el.style.getPropertyValue('--primary-color'), ''); + }); + + test('clears --primary-color when color is empty', async () => { + const el = await fixture(html` + + `); + el.updateModalOptions({ nid: '1', color: '#027fe5' }); + await el.updateComplete; + el.updateModalOptions({ nid: '1', color: '' }); + await el.updateComplete; + assert.equal(el.style.getPropertyValue('--primary-color'), ''); + }); + }); });