From 2414c62c2ad87c71852a251b9fcb7bc616dc241a Mon Sep 17 00:00:00 2001 From: Ankita Das Date: Sat, 4 Apr 2026 12:51:26 +0530 Subject: [PATCH 1/3] Fix XSS vulnerability by replacing innerHTML with safe DOM methods --- package-lock.json | 1 - packages/extension/src/popup.js | 18 +++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index bd5d59e..65f5c4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,7 +4,6 @@ "requires": true, "packages": { "": { - "name": "ExtensionShield", "devDependencies": { "dotenv": "^16.4.5", "resend": "^4.0.0", diff --git a/packages/extension/src/popup.js b/packages/extension/src/popup.js index 304aedd..62b5b26 100644 --- a/packages/extension/src/popup.js +++ b/packages/extension/src/popup.js @@ -602,7 +602,23 @@ evHtml = '
'; } - tr.innerHTML = '' + extHtml + '' + pillHtml + '' + evHtml + ''; + + + const td1 = document.createElement('td'); +td1.textContent = extHtml; + +const td2 = document.createElement('td'); +td2.style.textAlign = "center"; +td2.textContent = pillHtml; + +const td3 = document.createElement('td'); +td3.textContent = evHtml; + +tr.appendChild(td1); +tr.appendChild(td2); +tr.appendChild(td3); + + rows.appendChild(tr); } From 1825e834d5892329de7766674677b4ed9834fb93 Mon Sep 17 00:00:00 2001 From: Ankita Das Date: Sat, 4 Apr 2026 13:28:58 +0530 Subject: [PATCH 2/3] Fix: moved management permission to optional_permissions for better security --- packages/extension/src/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/extension/src/manifest.json b/packages/extension/src/manifest.json index 4cbdabb..ffc0f33 100644 --- a/packages/extension/src/manifest.json +++ b/packages/extension/src/manifest.json @@ -24,7 +24,7 @@ "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1EQJhE6eyAVdlLZ5lH0M+w1dcfVl3fOr4H1H2nw3aUksRoCwivfGOZNgGU1SrwdFeC7HlynvIn/w5YwKvCR+0EMsJAi7gp3yQj1NyegYf/d0EwBIHgJiGvrAn47zG/25GlrNdU4M+88B8kMquouPL6Sq5G99nYVkc6DNdE+8iIZe9aqQYIXFa7idAZ+qu44WUz4g+GfjketId+BkHYSN/RM7UY2iY8XEV/Zw5di1Jr0sGHQqZViTeN2wH+9/C5SeHTT3pIKAldCLkru++jFHc3YpAxcrxukkxh1R4a+H+FjpoqWYrfXVmiS8MMZoHZJcOJzEjDen6Wfq/YJKnxOYRwIDAQAB", "manifest_version": 3, "name": "Extension Shield", - "permissions": [ "management", "storage" ], + "optional_permissions": ["management"], "update_url": "https://clients2.google.com/service/update2/crx", "version": "1.1.0" } From 4a50c7365109936a8567e2b534f39d0da6bb3252 Mon Sep 17 00:00:00 2001 From: Ankita Das Date: Sat, 4 Apr 2026 13:41:36 +0530 Subject: [PATCH 3/3] Fix: added timeout handling to API calls using AbortController --- packages/extension/src/manifest.json | 3 ++- packages/extension/src/popup.js | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/extension/src/manifest.json b/packages/extension/src/manifest.json index ffc0f33..d61f52d 100644 --- a/packages/extension/src/manifest.json +++ b/packages/extension/src/manifest.json @@ -24,7 +24,8 @@ "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1EQJhE6eyAVdlLZ5lH0M+w1dcfVl3fOr4H1H2nw3aUksRoCwivfGOZNgGU1SrwdFeC7HlynvIn/w5YwKvCR+0EMsJAi7gp3yQj1NyegYf/d0EwBIHgJiGvrAn47zG/25GlrNdU4M+88B8kMquouPL6Sq5G99nYVkc6DNdE+8iIZe9aqQYIXFa7idAZ+qu44WUz4g+GfjketId+BkHYSN/RM7UY2iY8XEV/Zw5di1Jr0sGHQqZViTeN2wH+9/C5SeHTT3pIKAldCLkru++jFHc3YpAxcrxukkxh1R4a+H+FjpoqWYrfXVmiS8MMZoHZJcOJzEjDen6Wfq/YJKnxOYRwIDAQAB", "manifest_version": 3, "name": "Extension Shield", - "optional_permissions": ["management"], + "permissions": ["storage"], +"optional_permissions": ["management"], "update_url": "https://clients2.google.com/service/update2/crx", "version": "1.1.0" } diff --git a/packages/extension/src/popup.js b/packages/extension/src/popup.js index 62b5b26..41790af 100644 --- a/packages/extension/src/popup.js +++ b/packages/extension/src/popup.js @@ -4,6 +4,15 @@ var API = 'https://extensionshield.com'; var CACHE_TTL = 6 * 3600 * 1000; + function fetchWithTimeout(url, options = {}, timeout = 5000) { + const controller = new AbortController(); + const id = setTimeout(() => controller.abort(), timeout); + + return fetch(url, { + ...options, + signal: controller.signal + }).finally(() => clearTimeout(id)); +} var WEBSTORE_URL_PREFIX = 'https://chromewebstore.google.com/detail/x/'; var SCAN_POLL_INTERVAL = 3000; var SCAN_POLL_MAX = 60; @@ -426,7 +435,7 @@ function fetchResults(extId) { var url = API + '/api/scan/results/' + encodeURIComponent(extId); - return fetch(url).then(function (res) { + return fetchWithTimeout(url).then(function (res) { if (res.status === 404) return { _st: 'not_found' }; if (!res.ok) return { _st: 'error' }; return res.json().then(function (j) { j._st = 'ok'; return j; }); @@ -435,7 +444,7 @@ function triggerScan(extId) { var webstoreUrl = WEBSTORE_URL_PREFIX + encodeURIComponent(extId); - return fetch(API + '/api/scan/trigger', { + return fetchWithTimeout(API + '/api/scan/trigger', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url: webstoreUrl }) @@ -446,7 +455,7 @@ } function pollScanStatus(extId) { - return fetch(API + '/api/scan/status/' + encodeURIComponent(extId)) + return fetchWithTimeout(API + '/api/scan/status/' + encodeURIComponent(extId)) .then(function (res) { if (!res.ok) return { status: 'unknown' }; return res.json();