From 1bf69c4edcea5d28a1dd06fdd79191f2a61dd512 Mon Sep 17 00:00:00 2001 From: jason Date: Sat, 28 Feb 2026 12:51:30 -0700 Subject: [PATCH 1/2] fix(case-ioc): prevent JSON description popover crash blocking IOC edit (#849) --- ui/src/pages/case.ioc.js | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/ui/src/pages/case.ioc.js b/ui/src/pages/case.ioc.js index d111d021d..11fec3098 100644 --- a/ui/src/pages/case.ioc.js +++ b/ui/src/pages/case.ioc.js @@ -150,10 +150,21 @@ function get_case_ioc() { Table.clear(); Table.rows.add(data.data); - $('#ioc_table_wrapper').on('click', function(e){ - if($('.popover').length>1) - $('.popover').popover('hide'); - $(e.target).popover('toggle'); + $('#ioc_table_wrapper') + .off('click', '[data-toggle="popover"]') + .on('click', '[data-toggle="popover"]', function(event) { + event.preventDefault(); + + if ($('.popover').length > 1) { + $('.popover').popover('hide'); + } + + $(this).popover({ + content: function() { + const content = this.getAttribute('data-content'); + return content === null ? '' : content; + } + }).popover('toggle'); }); $('#ioc_table_wrapper').show(); @@ -468,4 +479,4 @@ $(document).ready(function(){ if (shared_id) { edit_ioc(shared_id); } -}); \ No newline at end of file +}); From fa0c8db326ecb53337b991c2015b5b4c0c073d0c Mon Sep 17 00:00:00 2001 From: jason Date: Sat, 28 Feb 2026 12:51:30 -0700 Subject: [PATCH 2/2] test(e2e): add IOC JSON-description click regression (#849) --- e2e/tests/administrator/case/ioc.spec.js | 36 +++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/e2e/tests/administrator/case/ioc.spec.js b/e2e/tests/administrator/case/ioc.spec.js index 0db39df0f..f07128377 100644 --- a/e2e/tests/administrator/case/ioc.spec.js +++ b/e2e/tests/administrator/case/ioc.spec.js @@ -28,6 +28,40 @@ test('should be able to update IOC', async ({ page }) => { await expect(page.getByRole('link', { name: newIocValue })).toBeVisible(); }); +test('should open IOC editor when IOC description is JSON', async ({ page, rest }) => { + const caseIdentifier = await Api.createCase(rest); + const iocValue = `IOC value - ${crypto.randomUUID()}`; + const iocDescription = JSON.stringify({ + error: '', + name: 'sampleLookupNumber', + parameters: { + add_on: 'telo_cnam', + caller_name: true, + carrier: true, + pstn: '19999999999' + } + }); + + const pageErrors = []; + page.on('pageerror', error => pageErrors.push(error.message)); + + await rest.post(`/api/v2/cases/${caseIdentifier}/iocs`, { + data: { + ioc_type_id: 1, + ioc_value: iocValue, + ioc_tlp_id: 2, + ioc_description: iocDescription, + ioc_tags: '' + } + }); + + await page.goto(`/case/ioc?cid=${caseIdentifier}`); + await page.getByRole('link', { name: iocValue }).click(); + + await expect(page.getByRole('button', { name: 'Update' })).toBeVisible(); + expect(pageErrors.filter(error => error.includes('TOOLTIP: Option "content"')).length).toBe(0); +}); + test('should not be able to create an IOC with the same type and value', async ({ page }) => { const iocValue = `IOC value - ${crypto.randomUUID()}`; @@ -89,4 +123,4 @@ test('should be able to update IOC custom attribute', async ({ page, rest }) => partial_overwrite: false } }) -}); \ No newline at end of file +});