Skip to content

Conversation

@MWG-Logan
Copy link
Member

No description provided.

JohnDuprey and others added 30 commits September 30, 2025 20:01
- Removed flickers when blocked page got displayed (you can clearly see text fields getting updated).

- Popup display used a temporary white background color, used theme color instead tro fix the white flash effect (especially visible with dark theme).
commit 638c177
Merge: 4f8d57e 650a780
Author: KelvinTegelaar <[email protected]>
Date:   Tue Oct 21 19:46:48 2025 +0200

    Merge pull request CyberDrain#90 from PeakeIT/main

commit 650a780
Author: Brandon Rutledge <[email protected]>
Date:   Thu Oct 16 18:12:59 2025 -0400

    fix: urlAllowlist registry entries to be in the correct format and Edge pinning in the ADMX
Added test pages for local file testing/detection
Added console log dev setting performance
Added regex caching performance
Added dom caching performance
Test Pages and Performance Improvements
json escaping for regexes
Fixed bug where custom rules URLs reverted to defaults after save.

- Save only user overrides to local storage, not entire merged config
- Sanitize empty URLs to fall back to defaults
- Respect enterprise policy precedence over user settings
- Add config reload capability to DetectionRulesManager
- Add comprehensive test suite (13 tests, all passing)

Closes CyberDrain#87
fix: custom detection rules URL not persisting
- Removed flickers when blocked page got displayed (you can clearly see text fields getting updated).

- Popup display used a temporary white background color, used theme color instead tro fix the white flash effect (especially visible with dark theme).
JohnDuprey and others added 24 commits November 5, 2025 13:41
Added test pages for local file testing/detection
Added console log dev setting performance
Added regex caching performance
Added dom caching performance
json escaping for regexes
Fixed bug where custom rules URLs reverted to defaults after save.

- Save only user overrides to local storage, not entire merged config
- Sanitize empty URLs to fall back to defaults
- Respect enterprise policy precedence over user settings
- Add config reload capability to DetectionRulesManager
- Add comprehensive test suite (13 tests, all passing)

Closes CyberDrain#87
- added test script for quick dev setup on registry settings
- added generic webhook handling with actions
- added report false positive button with success/error logic
- added github to the default rules to prevent detection
Added refreshToken input to Google Refresh Token workflow.

Signed-off-by: John Duprey <[email protected]>
Added permissions for content write access in jobs.

Signed-off-by: John Duprey <[email protected]>
This script removes specific Chrome and Edge extension settings from the Windows registry, including managed storage and extension settings keys.

Signed-off-by: Roel van der Wegen <[email protected]>
Copilot AI review requested due to automatic review settings November 17, 2025 17:37
Comment on lines +11 to +32
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: cardinalby/export-env-action@66657b34899a2d695434ed060d9f2215db9b4035
with:
envFile: './.github/workflows/constants.env'
expand: true

- name: Build, test and pack to zip
id: build
uses: ./.github/workflows/actions/build-test-pack
with:
# pack zip only for pull requests or workflow_dispatch events
doNotPackZip: ${{ github.event_name == 'push' && 'true' || 'false'}}

- name: Upload zip file artifact
if: github.event_name != 'push'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
with:
name: ${{ env.ZIP_FILE_NAME }}
path: ${{ env.ZIP_FILE_PATH }} No newline at end of file

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI about 1 month ago

The best way to fix the problem is to add a permissions block at the root of the workflow file (just under the name and prior to the on: block, or right after the on: block), specifying only the minimum permissions required. In most cases, contents: read is sufficient for build/test jobs. If all steps in this workflow only need to checkout code and upload artifacts, contents: read suffices. Add this block to the top of .github/workflows/build-and-test.yml. No other steps, methods, imports, or variable definitions are required.


Suggested changeset 1
.github/workflows/build-and-test.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -1,4 +1,6 @@
 name: Build and test
+permissions:
+  contents: read
 on:
   pull_request:
   push:
EOF
@@ -1,4 +1,6 @@
name: Build and test
permissions:
contents: read
on:
pull_request:
push:
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +8 to +14
runs-on: ubuntu-latest
steps:
- uses: cardinalby/google-api-fetch-token-action@24c99245e2a2494cc4c4b1037203d319a184b15b
with:
clientId: ${{ secrets.G_CLIENT_ID }}
clientSecret: ${{ secrets.G_CLIENT_SECRET }}
refreshToken: ${{ secrets.G_REFRESH_TOKEN }}

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {}

Copilot Autofix

AI about 1 month ago

To fix the problem, you need to add a permissions block to the workflow. Since the shown job only fetches a Google API token and does not interact with the GitHub API for creating/modifying content or PRs, it needs a minimal permissions grant—contents: read or possibly even none in some cases. The safest fix is to add permissions: contents: read at the workflow root, which will ensure the job token can only read repository contents and cannot perform any write operations. This block should be inserted just after the workflow name and before the on: key.


Suggested changeset 1
.github/workflows/google-refresh-token.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/google-refresh-token.yml b/.github/workflows/google-refresh-token.yml
--- a/.github/workflows/google-refresh-token.yml
+++ b/.github/workflows/google-refresh-token.yml
@@ -1,4 +1,6 @@
 name: Google Refresh Token
+permissions:
+  contents: read
 on:
   schedule:
     - cron:  '0 3 2 * *' # At 03:00 on day-of-month 2
EOF
@@ -1,4 +1,6 @@
name: Google Refresh Token
permissions:
contents: read
on:
schedule:
- cron: '0 3 2 * *' # At 03:00 on day-of-month 2
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +19 to +107
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.environment }}
outputs:
result: ${{ steps.webStorePublish.outcome }}
releaseUploadUrl: ${{ steps.getZipAsset.outputs.releaseUploadUrl }}
steps:
- name: Get the next attempt number
id: getNextAttemptNumber
uses: cardinalby/js-eval-action@b34865f1d9cfdf35356013627474857cfe0d5091
env:
attemptNumber: ${{ github.event.inputs.attemptNumber }}
maxAttempts: ${{ github.event.inputs.maxAttempts }}
with:
expression: |
{
const
attempt = parseInt(env.attemptNumber),
max = parseInt(env.maxAttempts);
assert(attempt && max && max >= attempt);
return attempt < max ? attempt + 1 : '';
}
- uses: actions/checkout@v4

- uses: cardinalby/export-env-action@66657b34899a2d695434ed060d9f2215db9b4035
with:
envFile: './.github/workflows/constants.env'
expand: true

- name: Obtain packed zip
id: getZipAsset
uses: ./.github/workflows/actions/get-zip-asset
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}

- name: Fetch Google API access token
id: fetchAccessToken
uses: cardinalby/google-api-fetch-token-action@24c99245e2a2494cc4c4b1037203d319a184b15b
with:
clientId: ${{ secrets.G_CLIENT_ID }}
clientSecret: ${{ secrets.G_CLIENT_SECRET }}
refreshToken: ${{ secrets.G_REFRESH_TOKEN }}

- name: Upload to Google Web Store
id: webStoreUpload
continue-on-error: true
uses: cardinalby/webext-buildtools-chrome-webstore-upload-action@8db7a005529498d95d3e2e0166f6f4050d2b96a5
with:
zipFilePath: ${{ env.ZIP_FILE_PATH }}
extensionId: ${{ secrets.G_EXTENSION_ID }}
apiAccessToken: ${{ steps.fetchAccessToken.outputs.accessToken }}
waitForUploadCheckCount: 10
waitForUploadCheckIntervalMs: 180000 # 3 minutes

# Schedule a next attempt if store refused to accept new version because it
# still has a previous one in review
- name: Start the next attempt with the delay
uses: aurelien-baudet/workflow-dispatch@93e95b157d791ae7f42aef8f8a0d3d723eba1c31 # pin@v2
if: |
steps.getNextAttemptNumber.outputs.result &&
steps.webStoreUpload.outputs.inReviewError == 'true'
with:
workflow: ${{ github.workflow }}
token: ${{ secrets.WORKFLOWS_TOKEN }}
wait-for-completion: false
inputs: |
{
"attemptNumber": "${{ steps.getNextAttemptNumber.outputs.result }}",
"maxAttempts": "${{ github.event.inputs.maxAttempts }}",
"environment": "12hoursDelay"
}
- name: Abort on unrecoverable upload error
if: |
!steps.webStoreUpload.outputs.newVersion &&
steps.webStoreUpload.outputs.sameVersionAlreadyUploadedError != 'true'
run: exit 1

- name: Publish on Google Web Store
id: webStorePublish
if: |
steps.webStoreUpload.outputs.newVersion ||
steps.webStoreUpload.outputs.sameVersionAlreadyUploadedError == 'true'
uses: cardinalby/webext-buildtools-chrome-webstore-publish-action@d39ebd4ab4ea4b44498bf5fc34d4b3db7706f1ed
with:
extensionId: ${{ secrets.G_EXTENSION_ID }}
apiAccessToken: ${{ steps.fetchAccessToken.outputs.accessToken }}

download-published-crx:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI about 1 month ago

To fix the problem, add an explicit permissions block at the workflow root (just after the name: and before on:) to set the least privilege required for the jobs. A minimal safe starting point is contents: read. If any jobs require elevated permissions (such as uploading release assets, which may need contents: write), you can specify more granular permissions in those jobs, but for this fix, set permissions: contents: read at the top level. This will restrict the GITHUB_TOKEN to read-only by default for all jobs unless overridden.

In .github/workflows/publish-on-chrome-webstore.yml, add the following at the top:

permissions:
  contents: read

This change does not alter the functionality of the workflow, but rather secures it by defining the permissions scope explicitly.


Suggested changeset 1
.github/workflows/publish-on-chrome-webstore.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/publish-on-chrome-webstore.yml b/.github/workflows/publish-on-chrome-webstore.yml
--- a/.github/workflows/publish-on-chrome-webstore.yml
+++ b/.github/workflows/publish-on-chrome-webstore.yml
@@ -1,4 +1,6 @@
 name: publish-on-chrome-web-store
+permissions:
+  contents: read
 on:
   workflow_dispatch:
     inputs:
EOF
@@ -1,4 +1,6 @@
name: publish-on-chrome-web-store
permissions:
contents: read
on:
workflow_dispatch:
inputs:
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +108 to +142
needs: publish-on-webstore
if: needs.publish-on-webstore.outputs.result == 'success'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: cardinalby/export-env-action@66657b34899a2d695434ed060d9f2215db9b4035
with:
envFile: './.github/workflows/constants.env'
expand: true

- name: Download published crx file
id: gWebStoreDownloadCrx
uses: cardinalby/webext-buildtools-chrome-webstore-download-crx-action@7de7ffb52fac6255a343c5e982871eb23cbee253
with:
extensionId: ${{ secrets.G_EXTENSION_ID }}
crxFilePath: ${{ env.WEBSTORE_CRX_FILE_PATH }}

- name: Upload webstore published crx release asset
if: needs.publish-on-webstore.outputs.releaseUploadUrl
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.publish-on-webstore.outputs.releaseUploadUrl }}
asset_path: ${{ env.WEBSTORE_CRX_FILE_PATH }}
asset_name: ${{ env.WEBSTORE_CRX_FILE_NAME }}
asset_content_type: application/x-chrome-extension

- name: Upload webstore crx file artifact to workflow
if: '!needs.publish-on-webstore.outputs.releaseUploadUrl'
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4
with:
name: ${{ env.WEBSTORE_CRX_FILE_NAME }}
path: ${{ env.WEBSTORE_CRX_FILE_PATH }}

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI about 1 month ago

To address this issue, add a permissions: block to the workflow YAML (.github/workflows/publish-on-chrome-webstore.yml). The best practice is to add the block at the top level, so it applies to all jobs in the workflow, unless some jobs specifically require different, broader permissions. In this case, since the jobs appear to primarily read repository contents and upload release artifacts (actions which require contents: read and contents: write), you may set contents: read at workflow level as the starting point, then add broader permissions for jobs that require them (e.g., download-published-crx for uploading release assets may need contents: write). For a minimal fix, simply add permissions: contents: read at the workflow level.

This change should be made at the beginning of the workflow file, after the name: and before the on: block, as shown in the example. No additional dependencies or method changes are required.


Suggested changeset 1
.github/workflows/publish-on-chrome-webstore.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/publish-on-chrome-webstore.yml b/.github/workflows/publish-on-chrome-webstore.yml
--- a/.github/workflows/publish-on-chrome-webstore.yml
+++ b/.github/workflows/publish-on-chrome-webstore.yml
@@ -1,4 +1,6 @@
 name: publish-on-chrome-web-store
+permissions:
+  contents: read
 on:
   workflow_dispatch:
     inputs:
EOF
@@ -1,4 +1,6 @@
name: publish-on-chrome-web-store
permissions:
contents: read
on:
workflow_dispatch:
inputs:
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +6 to +27
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: cardinalby/export-env-action@66657b34899a2d695434ed060d9f2215db9b4035
with:
envFile: './.github/workflows/constants.env'
expand: true

- name: Obtain packed zip
uses: ./.github/workflows/actions/get-zip-asset
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}

- name: Deploy to Edge Addons
uses: wdzeng/edge-addon@fe088a3bb9bf7c3f1cab08df6269664b9f7bf4fd # [email protected]
with:
product-id: ${{ secrets.EDGE_PRODUCT_ID }}
zip-path: ${{ env.ZIP_FILE_PATH }}
client-id: ${{ secrets.EDGE_CLIENT_ID }}
client-secret: ${{ secrets.EDGE_CLIENT_SECRET }}
access-token-url: ${{ secrets.EDGE_ACCESS_TOKEN_URL }} No newline at end of file

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI about 1 month ago

To fix this problem, you should add an explicit permissions block at either the workflow or job level. Since all jobs here are relevant to publishing/deploying (no mention of multiple jobs or jobs requiring different sets of permissions), you can specify the block at the top level for clarity and security. The minimal required permission for read-only repository access is contents: read. However, if any step of the job needs more (for example, to create releases, upload artifacts, or interact with pull requests), you may need to extend these. According to the steps shown—where the job checks out the repository and accesses secrets, but does not modify repository contents—contents: read should be sufficient.

You will add the following to the top of the workflow file, after the name: line, to constrain the GITHUB_TOKEN permissions:

permissions:
  contents: read

This should be line 2, shifting all subsequent lines down by one.


Suggested changeset 1
.github/workflows/publish-on-edge-add-ons.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/publish-on-edge-add-ons.yml b/.github/workflows/publish-on-edge-add-ons.yml
--- a/.github/workflows/publish-on-edge-add-ons.yml
+++ b/.github/workflows/publish-on-edge-add-ons.yml
@@ -1,4 +1,6 @@
 name: publish-on-edge-add-ons
+permissions:
+  contents: read
 on:
   workflow_dispatch:
 jobs:
EOF
@@ -1,4 +1,6 @@
name: publish-on-edge-add-ons
permissions:
contents: read
on:
workflow_dispatch:
jobs:
Copilot is powered by AI and may make mistakes. Always verify output.
Comment on lines +9 to +71
if: github.ref_type == 'tag'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: cardinalby/export-env-action@66657b34899a2d695434ed060d9f2215db9b4035
with:
envFile: './.github/workflows/constants.env'
expand: true

- name: Look for existing release
id: getRelease
uses: cardinalby/git-get-release-action@cedef2faf69cb7c55b285bad07688d04430b7ada
continue-on-error: true
with:
tag: ${{ github.ref_name }}
env:
GITHUB_TOKEN: ${{ github.token }}

- name: Build, test and pack to zip
id: buildPack
if: steps.getRelease.outcome != 'success'
uses: ./.github/workflows/actions/build-test-pack

- name: Create Release
id: createRelease
if: steps.getRelease.outcome != 'success'
uses: ncipollo/release-action@58ae73b360456532aafd58ee170c045abbeaee37 # pin@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
draft: 'true'

- name: Upload zip asset to the release
if: steps.getRelease.outcome != 'success'
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.createRelease.outputs.upload_url }}
asset_path: ${{ env.ZIP_FILE_PATH }}
asset_name: ${{ env.ZIP_FILE_NAME }}
asset_content_type: application/zip

# Should trigger build-assets-on-release.yml
- name: Publish release
if: steps.getRelease.outcome != 'success'
uses: eregon/publish-release@c2c0552ef2dd8209aea2a95c940a156eb8f6e9c1 # pin@v1
env:
GITHUB_TOKEN: ${{ secrets.WORKFLOWS_TOKEN }}
with:
release_id: ${{ steps.createRelease.outputs.id }}

- name: Publish on Chrome Webstore
uses: benc-uk/workflow-dispatch@4c044c1613fabbe5250deadc65452d54c4ad4fc7 # pin@v1
with:
workflow: publish-on-chrome-web-store
token: ${{ secrets.WORKFLOWS_TOKEN }}

- name: Publish on Edge Add-ons
uses: benc-uk/workflow-dispatch@4c044c1613fabbe5250deadc65452d54c4ad4fc7 # pin@v1
with:
workflow: publish-on-edge-add-ons
token: ${{ secrets.WORKFLOWS_TOKEN }} No newline at end of file

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}

Copilot Autofix

AI about 1 month ago

The best way to fix the problem is to explicitly declare a top-level permissions block in the workflow YAML file, granting the least amount of privilege required for the workflow to succeed. For most of the steps in this workflow, write permission to contents is required (e.g., creating releases, uploading assets). In general, start with contents: write at the workflow level. If some jobs/steps need even less, consider scoping permissions to jobs; however, no evidence is shown here for finer granularity. Add the block right after the workflow name and before the on: key, following YAML conventions, as per GitHub Actions documentation. No additional imports or external libraries are required.


Suggested changeset 1
.github/workflows/publish-release-on-tag.yml

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/.github/workflows/publish-release-on-tag.yml b/.github/workflows/publish-release-on-tag.yml
--- a/.github/workflows/publish-release-on-tag.yml
+++ b/.github/workflows/publish-release-on-tag.yml
@@ -1,4 +1,6 @@
 name: Release and publish on tag
+permissions:
+  contents: write
 on:
   push:
     tags:
EOF
@@ -1,4 +1,6 @@
name: Release and publish on tag
permissions:
contents: write
on:
push:
tags:
Copilot is powered by AI and may make mistakes. Always verify output.
@MWG-Logan MWG-Logan merged commit 0a3cc67 into main Nov 17, 2025
14 checks passed
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces comprehensive webhook functionality, test infrastructure, improved configuration management, and enhanced development/deployment tooling for the Check extension.

  • Adds a unified webhook system supporting multiple event types (detection alerts, false positives, page blocks, rogue app detection)
  • Implements test infrastructure with Chrome API mocks and configuration persistence tests
  • Refactors configuration management to centralize customRulesUrl and improve user settings persistence
  • Enhances deployment with GitHub Actions workflows and enterprise policy updates

Reviewed Changes

Copilot reviewed 39 out of 39 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
scripts/modules/webhook-manager.js New webhook management system with unified payload structure for all event types
scripts/modules/config-manager.js Refactored config persistence to save only user overrides and migrate legacy settings
scripts/modules/detection-rules-manager.js Added configuration reload functionality
scripts/content.js Performance optimizations with regex caching, page source caching, and webhook integration
scripts/background.js Integrated webhook manager and delegated webhook sending to centralized manager
scripts/blocked.js Added false positive reporting functionality with webhook support
tests/config-persistence.test.js New test suite for configuration persistence and enterprise policy precedence
tests/helpers/chrome-mock.js Chrome API mock implementation for testing
tests/helpers/logger-mock.js Logger mock for test environment
test-pages/*.html Test pages for manual phishing detection validation
options/options.html Added generic webhook configuration UI
options/options.js Integrated webhook settings management
rules/detection-rules.json Updated regex patterns with escaped forward slashes and improved detection logic
manifest.json Added file:// protocol support for local testing
config/managed_schema.json Added genericWebhook schema for enterprise policies
docs/webhooks.md Comprehensive webhook documentation with payload examples
docs/settings/general.md Documentation for false positive webhook configuration
enterprise/admx/en-US/Check-Extension.adml Formatting improvements and companyURL policy addition
enterprise/*.ps1 New PowerShell scripts for testing and removal of extension policies
.github/workflows/*.yml New CI/CD workflows for building, testing, and publishing releases
blocked.html Added false positive reporting button and anti-flicker loading state
popup/popup.css Theme-aware loading screen colors
package.json Added test scripts for running test suites

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +608 to +625
// Check if false positive webhook is configured and show button accordingly
const falsePositiveBtn = document.getElementById("reportFalsePositiveBtn");
const genericWebhook = storageResult.genericWebhook;
if (genericWebhook && genericWebhook.enabled && genericWebhook.url) {
const events = genericWebhook.events || [];
if (events.includes("false_positive_report")) {
console.log("False positive webhook configured, showing report button");
webhookConfig = { url: genericWebhook.url };
if (falsePositiveBtn) {
falsePositiveBtn.style.display = "inline-block";
}
return;
}
}
console.log("No false positive webhook configured, hiding report button");
if (falsePositiveBtn) {
falsePositiveBtn.style.display = "none";
}
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The webhook URL and enabled state are not validated before sending the webhook. The code should validate that the URL is a valid HTTPS URL to prevent accidentally sending sensitive detection data over insecure HTTP connections.

Add validation like:

if (genericWebhook.url && !genericWebhook.url.startsWith('https://')) {
  console.error("Webhook URL must use HTTPS");
  return;
}

Copilot uses AI. Check for mistakes.
Comment on lines +131 to +205
async function reportFalsePositive() {
console.log("reportFalsePositive function called");

const reportBtn = document.getElementById("reportFalsePositiveBtn");

if (!webhookConfig || !webhookConfig.url) {
console.error("No webhook configured");
return;
}

try {
reportBtn.disabled = true;
reportBtn.textContent = "Sending...";
reportBtn.style.background = "#6b7280";
reportBtn.style.color = "white";

const payload = {
version: "1.0",
type: "false_positive_report",
timestamp: new Date().toISOString(),
source: "Check Extension",
extensionVersion: chrome.runtime.getManifest().version,
data: {
reportedUrl: document.getElementById("blockedUrl").textContent,
reportedReason: document.getElementById("blockReason").textContent,
reportTimestamp: new Date().toISOString(),
userAgent: navigator.userAgent,
browserInfo: {
platform: navigator.platform,
language: navigator.language,
vendor: navigator.vendor,
cookiesEnabled: navigator.cookieEnabled,
onLine: navigator.onLine
},
screenResolution: {
width: window.screen.width,
height: window.screen.height,
availWidth: window.screen.availWidth,
availHeight: window.screen.availHeight,
colorDepth: window.screen.colorDepth
},
detectionDetails: globalDetectionDetails || {},
userComments: null
}
};

console.log("Sending false positive report to:", webhookConfig.url);
console.log("Report payload:", payload);

const response = await fetch(webhookConfig.url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Webhook-Type": "false_positive_report",
"X-Webhook-Version": "1.0"
},
body: JSON.stringify(payload)
});

if (response.ok) {
console.log("False positive report sent successfully");
reportBtn.textContent = "Report Sent Successfully";
reportBtn.style.background = "#16a34a";
reportBtn.style.color = "white";
} else {
console.warn("False positive report failed with HTTP status:", response.status, response.statusText);
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
} catch (error) {
console.error("Failed to send false positive report:", error);
reportBtn.textContent = `Failed: ${error.message}`;
reportBtn.style.background = "#dc2626";
reportBtn.style.color = "white";
}
}
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reportFalsePositive function sends potentially sensitive detection details including page content, browser information, and screen resolution to an arbitrary webhook URL. There's no user consent or warning about what data is being sent when they click the "Report False Positive" button.

Consider adding a confirmation dialog that clearly explains what data will be sent, or providing a privacy notice near the button.

Copilot uses AI. Check for mistakes.
}
analysis.sheets.push(sheetInfo);
}
} catch (e) {}
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty catch blocks silently swallow errors, making debugging difficult. The webhook sending failures in the content script use .catch(err => { logger.warn(...) }) pattern, but here the error is completely ignored.

Consider at least logging the error:

} catch (e) {
  logger.warn("Failed to analyze stylesheets:", e);
}
Suggested change
} catch (e) {}
} catch (e) {
logger.warn("Failed to analyze stylesheets:", e);
}

Copilot uses AI. Check for mistakes.
Comment on lines +1145 to +1158
genericWebhook: {
enabled: this.elements.genericWebhookEnabled?.checked || false,
url: this.elements.genericWebhookUrl?.value || "",
events: [
"detection_alert",
"false_positive_report",
"page_blocked",
"rogue_app_detected",
"threat_detected",
"validation_event"
].filter(eventType =>
document.getElementById(`webhookEvent_${eventType}`)?.checked
)
},
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The generic webhook configuration lacks input validation in the UI. The webhook URL should be validated to ensure it's a valid HTTPS URL before saving. Currently, users could enter an invalid URL or an insecure HTTP URL, which would cause runtime errors or security issues.

Add URL validation in the save configuration logic similar to how other URLs are validated in the codebase.

Copilot uses AI. Check for mistakes.
Comment on lines +8 to +11
global.fetch = async () => ({
ok: false,
status: 404
});
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The test uses a mock fetch that always returns ok: false, status: 404. This setup is repeated in multiple test suites, creating code duplication. Consider extracting this into a helper function in the test setup or creating a reusable mock fetch fixture.

For example:

function createMockFetch(response = { ok: false, status: 404 }) {
  return async () => response;
}

Copilot uses AI. Check for mistakes.
Comment on lines +6 to +11
"^https:\\/\\/login\\.microsoftonline\\.(com|us)$",
"^https:\\/\\/login\\.microsoft\\.com$",
"^https:\\/\\/login\\.microsoft\\.net$",
"^https:\\/\\/login\\.windows\\.net$",
"^https:\\/\\/login\\.partner\\.microsoftonline\\.cn$",
"^https:\\/\\/login\\.live\\.com$"
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex patterns in the detection rules JSON file use escaped forward slashes (\/) which are unnecessary in JSON strings. JSON does not require escaping forward slashes, and while it's technically valid, it adds unnecessary complexity and makes the patterns harder to read.

For example, "^https:\\/\\/login\\.microsoftonline\\.(com|us)$" should be "^https://login\\.microsoftonline\\.(com|us)$".

Consider simplifying these patterns for better maintainability.

Copilot uses AI. Check for mistakes.
{
"id": "phi_006",
"pattern": "(?=.*(?:microsoft|office|365))(?=.*(?:login|password|signin))(?=.*form.*action)(?!.*login\\.microsoftonline\\.com)(?!.*\\.auth/login/)(?!.*azure\\s+static\\s+web\\s+apps)(?!.*easy\\s+auth)",
"pattern": "(?:microsoft|office|365).{0,2000}(?:login|password|signin).{0,500}form.{0,200}action(?!.*login\\.microsoftonline\\.com)(?!.*\\.auth/login/)(?!.*azure\\s+static\\s+web\\s+apps)(?!.*easy\\s+auth)",
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex pattern uses a greedy quantifier .{0,2000} which could cause performance issues when matching against large HTML documents. Consider using a non-greedy quantifier .{0,2000}? or a more specific pattern to improve regex performance and prevent potential regex denial-of-service (ReDoS) scenarios.

Suggested change
"pattern": "(?:microsoft|office|365).{0,2000}(?:login|password|signin).{0,500}form.{0,200}action(?!.*login\\.microsoftonline\\.com)(?!.*\\.auth/login/)(?!.*azure\\s+static\\s+web\\s+apps)(?!.*easy\\s+auth)",
"pattern": "(?:microsoft|office|365).{0,2000}?(?:login|password|signin).{0,500}form.{0,200}action(?!.*login\\.microsoftonline\\.com)(?!.*\\.auth/login/)(?!.*azure\\s+static\\s+web\\s+apps)(?!.*easy\\s+auth)",

Copilot uses AI. Check for mistakes.
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"matches": ["http://*/*", "https://*/*", "file:///*/*"],
Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The manifest.json adds support for "file:///*/*" URLs in content scripts. This allows the extension to run on local file:// URLs, which could be a security concern as it gives the extension access to the user's local file system content when viewing HTML files locally.

Consider whether this is truly necessary for the extension's functionality, or if it should be limited to specific use cases (like developer testing). If it's only for testing, consider documenting this clearly or providing a separate development manifest.

Suggested change
"matches": ["http://*/*", "https://*/*", "file:///*/*"],
"matches": ["http://*/*", "https://*/*"],

Copilot uses AI. Check for mistakes.
Comment on lines +163 to +190
function analyzeStylesheets() {
if (cachedStylesheetAnalysis) return cachedStylesheetAnalysis;
const analysis = { hasMicrosoftCSS: false, cssContent: "", sheets: [] };
try {
const styleSheets = Array.from(document.styleSheets);
for (const sheet of styleSheets) {
const sheetInfo = { href: sheet.href || "inline" };
if (sheet.href?.match(/msauth|msft|microsoft/i)) {
analysis.hasMicrosoftCSS = true;
}
try {
if (sheet.cssRules) {
analysis.cssContent +=
Array.from(sheet.cssRules)
.map((r) => r.cssText)
.join(" ") + " ";
sheetInfo.accessible = true;
}
} catch (e) {
sheetInfo.accessible = false;
}
analysis.sheets.push(sheetInfo);
}
} catch (e) {}
cachedStylesheetAnalysis = analysis;
return analysis;
}

Copy link

Copilot AI Nov 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused function analyzeStylesheets.

Suggested change
function analyzeStylesheets() {
if (cachedStylesheetAnalysis) return cachedStylesheetAnalysis;
const analysis = { hasMicrosoftCSS: false, cssContent: "", sheets: [] };
try {
const styleSheets = Array.from(document.styleSheets);
for (const sheet of styleSheets) {
const sheetInfo = { href: sheet.href || "inline" };
if (sheet.href?.match(/msauth|msft|microsoft/i)) {
analysis.hasMicrosoftCSS = true;
}
try {
if (sheet.cssRules) {
analysis.cssContent +=
Array.from(sheet.cssRules)
.map((r) => r.cssText)
.join(" ") + " ";
sheetInfo.accessible = true;
}
} catch (e) {
sheetInfo.accessible = false;
}
analysis.sheets.push(sheetInfo);
}
} catch (e) {}
cachedStylesheetAnalysis = analysis;
return analysis;
}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants