From 3bb1af5e3284198854866b640b45fb3534309409 Mon Sep 17 00:00:00 2001 From: martgil <46025304+martgil@users.noreply.github.com> Date: Mon, 6 Jul 2026 17:43:18 +0800 Subject: [PATCH 1/5] feat: improve regex for checking remote image url --- extension/js/common/core/common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/js/common/core/common.ts b/extension/js/common/core/common.ts index 81ace34c189..c222164081d 100644 --- a/extension/js/common/core/common.ts +++ b/extension/js/common/core/common.ts @@ -560,7 +560,7 @@ export const stringTuple = (...data: T): T => { }; export const checkValidURL = (url: string): boolean => { - const pattern = /(http|https):\/\/([a-z0-9-]+((\.[a-z0-9-]+)+)?)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@\-\/]))?/; + const pattern = /^https?:\/\/([a-z0-9-]+(\.[a-z0-9-]+)+)?(:\d+)?(\/[\w#!:.?+=&%@\-\/]*)?$/i; return pattern.test(url); }; From 470f958cd2f95f585356db41dc2fa9bb85e69efe Mon Sep 17 00:00:00 2001 From: martgil <46025304+martgil@users.noreply.github.com> Date: Mon, 6 Jul 2026 18:22:21 +0800 Subject: [PATCH 2/5] test: add test case for #6256 --- .../message-export-19f36e6fc5838dac.json | 68 +++++++++++++++++++ test/source/tests/decrypt.ts | 19 ++++++ 2 files changed, 87 insertions(+) create mode 100644 test/source/mock/google/exported-messages/message-export-19f36e6fc5838dac.json diff --git a/test/source/mock/google/exported-messages/message-export-19f36e6fc5838dac.json b/test/source/mock/google/exported-messages/message-export-19f36e6fc5838dac.json new file mode 100644 index 00000000000..00ebd01c807 --- /dev/null +++ b/test/source/mock/google/exported-messages/message-export-19f36e6fc5838dac.json @@ -0,0 +1,68 @@ +{ + "acctEmail": "flowcrypt.compatibility@gmail.com", + "full": { + "id": "19f36e6fc5838dac", + "threadId": "19f36e657937a128", + "labelIds": [ + "IMPORTANT", + "Label_15", + "SENT", + "INBOX" + ], + "snippet": "-----BEGIN PGP MESSAGE----- hQIMA0taL/zmLZUBAQ/+NXaeeEoxIYhjw/2feJ01HAH7d6rYc3KD2uEnICWjweCE +pr/dWbRMHtqre6w4N7AH27ykC120GKWTittRJmwQMGB91jdllOXvJIVDnxxcvnq 5k1YN/qDHXjnYjAOSYvWAsuihxSYQm2/", + "payload": { + "partId": "", + "mimeType": "text/plain", + "filename": "", + "headers": [ + { + "name": "MIME-Version", + "value": "1.0" + }, + { + "name": "Date", + "value": "Mon, 6 Jul 2026 18:08:55 +0800" + }, + { + "name": "Subject", + "value": "flowcrypt-browser issue #6257 test case" + }, + { + "name": "From", + "value": "sender@domain.com" + }, + { + "name": "To", + "value": "flowcrypt.compatibility@gmail.com" + }, + { + "name": "Content-Type", + "value": "text/plain; charset=\"UTF-8\"" + } + ], + "body": { + "size": 1259, + "data": "LS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tDQoNCmhRSU1BMHRhTC96bUxaVUJBUS8rTlhhZWVFb3hJWWhqdy8yZmVKMDFIQUg3ZDZyWWMzS0QydUVuSUNXandlQ0UNCitwci9kV2JSTUh0cXJlNnc0TjdBSDI3eWtDMTIwR0tXVGl0dFJKbXdRTUdCOTFqZGxsT1h2SklWRG54eGN2bnENCjVrMVlOL3FESFhqbllqQU9TWXZXQXN1aWh4U1lRbTIvZ0ExRUFaT29xNzllME1xN0N4eVdyY0pDUTIvQkNLNC8NCnN1dFdZK1haRFUwYVFXbnJrR0xIRlN2RXFBQ1M3T3c3dXBZdytSdU9GU1pIUXh6SVpueXRSOTBGWmZsYkkwdnANCkc5L0cwRVRQNU0valFmejRJZWRyNmFCK2dJelFncHdMSjRSN2JUTTVRU1FaNGlYak9DbWlpMW5tR2NvMGhweDENCjE4TnRzUzdnU2prSlBUeW1VcDFWSE9ucUlwOFY2NkdvSTZUMzI4Z1dYelJqZVRsa2JtR1dCcURacEJRUXE5blENClExZmY2aWl1UGp2MXZCdUU5SGRwdTluNnFyb1NkVmk4eDR6UTNFOWthUkNsMTBBUllZYWxsOU91b29TUlBLMGINCldMdXNMRTlUOW1Eem16YlNGamJuME1qQ2xZYmdzV2ZpcWNsYURncUFraVlZZ0tYME85elZJc2VOWkZMQ1FNamINCm44dTJOOG5BSEg2Y08wSFg4Y3B3bmRDd0NremxaSnF1NVB3Tllwc3N3alhUdCtOQWZZSy9kOXNaVFFTL2VteW0NCnBUK3V1emphUkJieVA3MHlzVUlyZUZpdTF6UHlRZGRDcnhSRWwwVERCWmZhdmxTamJJQTF3b3hBYlMyei8wTFYNCjhuZ0R2N1M3cXhGV0c4NENNZk1pMitZczZUd2F3SDBVZzJ2QXFYalNkNW1Rbi91M3B6NnFpUHd0T1FMZXlwL1MNCndJOEJMZU9hQUtqa0lSZ0NiOWhYSVVqMkhDRVlQMHhQcTVMTW9Yd1NPenNtRnEwcFh5d2cyalcycE56UTJRUnANCjVBbFVNczY2ZmZaKzFKUXFvc25qR0JlNjVRNHZOWUwxWDlDV3VwZVpLWXZrWFNnNFJiVlpneHVlbE9sdGFMSTQNCmR1QzZPQVgyTDgvM2VENjl4RXpUMitzc0pIdzdlbC96b1JjM2M5WUh3OWVaUGdnRnMwU25SemVDc1B3Um9MMEQNCkhhWGFRMFdic3hvYWxzUndnZ1NiaE5hS09RRWxJdjBnaXNsZG4zM0lBS3pvUlhvaGNUYzhIbjRqa0hXMzBuUjcNCmR2QmdvQXpReHZZRnVlNXhyZG9EaTZqdmRkaExxU1cvbEVweUtVdkhKclJ0bVR6YTh4cmQ4VmVzekd5MW40ak0NCklCY055WVN0U2dVQm5adnl0SmJXejFtMGw5eHUxOUVUejlxNTB4SHZ5eGZsejhYa3B2cW1YaHNoVXpZODFXTFcNClhCOTN1clFVU0lSSkl0UXJBb1lNU2R2cGtCUUtMeGttQlVHL0F1TGRiUzFtV1lWQWxwMFhGU1dURjE2UEFOV2INCllnPT0NCj1FWUdEDQotLS0tLUVORCBQR1AgTUVTU0FHRS0tLS0tDQo=" + } + }, + "sizeEstimate": 1625, + "historyId": "1500076", + "internalDate": "1783332535000" + }, + "attachments": {}, + "raw": { + "id": "19f36e6fc5838dac", + "threadId": "19f36e657937a128", + "labelIds": [ + "IMPORTANT", + "Label_15", + "SENT", + "INBOX" + ], + "snippet": "-----BEGIN PGP MESSAGE----- hQIMA0taL/zmLZUBAQ/+NXaeeEoxIYhjw/2feJ01HAH7d6rYc3KD2uEnICWjweCE +pr/dWbRMHtqre6w4N7AH27ykC120GKWTittRJmwQMGB91jdllOXvJIVDnxxcvnq 5k1YN/qDHXjnYjAOSYvWAsuihxSYQm2/", + "sizeEstimate": 1625, + "raw": "TUlNRS1WZXJzaW9uOiAxLjANCkRhdGU6IE1vbiwgNiBKdWwgMjAyNiAxODowODo1NSArMDgwMA0KTWVzc2FnZS1JRDogPENBS2J1TFRxTWRFUW4teXdONWJPNFFRVk9ZazJPMGFvTmFhX29mcURnQ2Y5YVdDX2MyQUBtYWlsLmdtYWlsLmNvbT4NClN1YmplY3Q6IGZsb3djcnlwdC1icm93c2VyIGlzc3VlICM2MjU3IHRlc3QgY2FzZQ0KRnJvbTogRmxvd0NyeXB0IENvbXBhdGliaWxpdHkgPGZsb3djcnlwdC5jb21wYXRpYmlsaXR5QGdtYWlsLmNvbT4NClRvOiBGbG93Q3J5cHQgQ29tcGF0aWJpbGl0eSA8Zmxvd2NyeXB0LmNvbXBhdGliaWxpdHlAZ21haWwuY29tPg0KQ29udGVudC1UeXBlOiB0ZXh0L3BsYWluOyBjaGFyc2V0PSJVVEYtOCINCg0KLS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tDQoNCmhRSU1BMHRhTC96bUxaVUJBUS8rTlhhZWVFb3hJWWhqdy8yZmVKMDFIQUg3ZDZyWWMzS0QydUVuSUNXandlQ0UNCitwci9kV2JSTUh0cXJlNnc0TjdBSDI3eWtDMTIwR0tXVGl0dFJKbXdRTUdCOTFqZGxsT1h2SklWRG54eGN2bnENCjVrMVlOL3FESFhqbllqQU9TWXZXQXN1aWh4U1lRbTIvZ0ExRUFaT29xNzllME1xN0N4eVdyY0pDUTIvQkNLNC8NCnN1dFdZK1haRFUwYVFXbnJrR0xIRlN2RXFBQ1M3T3c3dXBZdytSdU9GU1pIUXh6SVpueXRSOTBGWmZsYkkwdnANCkc5L0cwRVRQNU0valFmejRJZWRyNmFCK2dJelFncHdMSjRSN2JUTTVRU1FaNGlYak9DbWlpMW5tR2NvMGhweDENCjE4TnRzUzdnU2prSlBUeW1VcDFWSE9ucUlwOFY2NkdvSTZUMzI4Z1dYelJqZVRsa2JtR1dCcURacEJRUXE5blENClExZmY2aWl1UGp2MXZCdUU5SGRwdTluNnFyb1NkVmk4eDR6UTNFOWthUkNsMTBBUllZYWxsOU91b29TUlBLMGINCldMdXNMRTlUOW1Eem16YlNGamJuME1qQ2xZYmdzV2ZpcWNsYURncUFraVlZZ0tYME85elZJc2VOWkZMQ1FNamINCm44dTJOOG5BSEg2Y08wSFg4Y3B3bmRDd0NremxaSnF1NVB3Tllwc3N3alhUdCtOQWZZSy9kOXNaVFFTL2VteW0NCnBUK3V1emphUkJieVA3MHlzVUlyZUZpdTF6UHlRZGRDcnhSRWwwVERCWmZhdmxTamJJQTF3b3hBYlMyei8wTFYNCjhuZ0R2N1M3cXhGV0c4NENNZk1pMitZczZUd2F3SDBVZzJ2QXFYalNkNW1Rbi91M3B6NnFpUHd0T1FMZXlwL1MNCndJOEJMZU9hQUtqa0lSZ0NiOWhYSVVqMkhDRVlQMHhQcTVMTW9Yd1NPenNtRnEwcFh5d2cyalcycE56UTJRUnANCjVBbFVNczY2ZmZaKzFKUXFvc25qR0JlNjVRNHZOWUwxWDlDV3VwZVpLWXZrWFNnNFJiVlpneHVlbE9sdGFMSTQNCmR1QzZPQVgyTDgvM2VENjl4RXpUMitzc0pIdzdlbC96b1JjM2M5WUh3OWVaUGdnRnMwU25SemVDc1B3Um9MMEQNCkhhWGFRMFdic3hvYWxzUndnZ1NiaE5hS09RRWxJdjBnaXNsZG4zM0lBS3pvUlhvaGNUYzhIbjRqa0hXMzBuUjcNCmR2QmdvQXpReHZZRnVlNXhyZG9EaTZqdmRkaExxU1cvbEVweUtVdkhKclJ0bVR6YTh4cmQ4VmVzekd5MW40ak0NCklCY055WVN0U2dVQm5adnl0SmJXejFtMGw5eHUxOUVUejlxNTB4SHZ5eGZsejhYa3B2cW1YaHNoVXpZODFXTFcNClhCOTN1clFVU0lSSkl0UXJBb1lNU2R2cGtCUUtMeGttQlVHL0F1TGRiUzFtV1lWQWxwMFhGU1dURjE2UEFOV2INCllnPT0NCj1FWUdEDQotLS0tLUVORCBQR1AgTUVTU0FHRS0tLS0tDQo=", + "historyId": "1500076", + "internalDate": "1783332535000" + } +} \ No newline at end of file diff --git a/test/source/tests/decrypt.ts b/test/source/tests/decrypt.ts index 32361706b2a..1c16f4b06eb 100644 --- a/test/source/tests/decrypt.ts +++ b/test/source/tests/decrypt.ts @@ -166,6 +166,25 @@ export const defineDecryptTests = (testVariant: TestVariant, testWithBrowser: Te }) ); + test( + `decrypt - show remote image warning regardless of URL scheme casing`, + testWithBrowser(async (t, browser) => { + const threadId = '19f36e6fc5838dac'; + const { acctEmail } = await BrowserRecipe.setupCommonAcctWithAttester(t, browser, 'compatibility'); + const inboxPage = await browser.newExtensionPage(t, `chrome/settings/inbox/inbox.htm?acctEmail=${acctEmail}&threadId=${threadId}`); + await inboxPage.waitForSelTestState('ready'); + await inboxPage.waitAll('iframe'); + const pgpBlock = await inboxPage.getFrame(['pgp_block.htm']); + await pgpBlock.waitAll('@remote-image-container img'); + const src = await pgpBlock.target.evaluate(() => { + return document.querySelector('[data-test="remote-image-container"] img')?.getAttribute('src'); + }); + expect(src).to.match(/^HTTPS/); + await pgpBlock.waitForContent('@remote-image-container', 'Authenticity of this remote image cannot be verified.'); + await inboxPage.close(); + }) + ); + test( `decrypt - show inline image when user clicks show image`, testWithBrowser(async (t, browser) => { From a8f75fb4da741d5c34ba099b0e442456ac2aefc1 Mon Sep 17 00:00:00 2001 From: martgil <46025304+martgil@users.noreply.github.com> Date: Mon, 6 Jul 2026 20:03:04 +0800 Subject: [PATCH 3/5] test: fix incorrect threadId --- test/source/tests/decrypt.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/source/tests/decrypt.ts b/test/source/tests/decrypt.ts index 1c16f4b06eb..f6ca36a109f 100644 --- a/test/source/tests/decrypt.ts +++ b/test/source/tests/decrypt.ts @@ -169,7 +169,7 @@ export const defineDecryptTests = (testVariant: TestVariant, testWithBrowser: Te test( `decrypt - show remote image warning regardless of URL scheme casing`, testWithBrowser(async (t, browser) => { - const threadId = '19f36e6fc5838dac'; + const threadId = '19f36e657937a128'; const { acctEmail } = await BrowserRecipe.setupCommonAcctWithAttester(t, browser, 'compatibility'); const inboxPage = await browser.newExtensionPage(t, `chrome/settings/inbox/inbox.htm?acctEmail=${acctEmail}&threadId=${threadId}`); await inboxPage.waitForSelTestState('ready'); From 507234cd4fab34b18a81991b06c5d13dbde69bd7 Mon Sep 17 00:00:00 2001 From: martgil <46025304+martgil@users.noreply.github.com> Date: Tue, 7 Jul 2026 11:01:06 +0800 Subject: [PATCH 4/5] wip --- test/source/tests/decrypt.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/test/source/tests/decrypt.ts b/test/source/tests/decrypt.ts index f6ca36a109f..e6373bd60f0 100644 --- a/test/source/tests/decrypt.ts +++ b/test/source/tests/decrypt.ts @@ -175,7 +175,6 @@ export const defineDecryptTests = (testVariant: TestVariant, testWithBrowser: Te await inboxPage.waitForSelTestState('ready'); await inboxPage.waitAll('iframe'); const pgpBlock = await inboxPage.getFrame(['pgp_block.htm']); - await pgpBlock.waitAll('@remote-image-container img'); const src = await pgpBlock.target.evaluate(() => { return document.querySelector('[data-test="remote-image-container"] img')?.getAttribute('src'); }); From 5d441f23ec5579783d4963fec5831ca425e148a6 Mon Sep 17 00:00:00 2001 From: martgil <46025304+martgil@users.noreply.github.com> Date: Tue, 7 Jul 2026 17:26:51 +0800 Subject: [PATCH 5/5] refactor: checkValidURL() --- extension/js/common/core/common.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/extension/js/common/core/common.ts b/extension/js/common/core/common.ts index c222164081d..d5ccf6d5cde 100644 --- a/extension/js/common/core/common.ts +++ b/extension/js/common/core/common.ts @@ -560,8 +560,12 @@ export const stringTuple = (...data: T): T => { }; export const checkValidURL = (url: string): boolean => { - const pattern = /^https?:\/\/([a-z0-9-]+(\.[a-z0-9-]+)+)?(:\d+)?(\/[\w#!:.?+=&%@\-\/]*)?$/i; - return pattern.test(url); + try { + const parsedUrl = new URL(url); + return parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:'; + } catch { + return false; + } }; /**