Skip to content

fix(follow-up): restore custom HTTPS backend reachability via optional host permissions#13

Merged
DYAI2025 merged 1 commit into
feat/extension-fix-and-hardeningfrom
codex/fix-high-priority-bug-in-manifest.json
May 4, 2026
Merged

fix(follow-up): restore custom HTTPS backend reachability via optional host permissions#13
DYAI2025 merged 1 commit into
feat/extension-fix-and-hardeningfrom
codex/fix-high-priority-bug-in-manifest.json

Conversation

@DYAI2025

@DYAI2025 DYAI2025 commented May 4, 2026

Copy link
Copy Markdown
Owner

Motivation

  • Removing the wildcard https://*/* from host_permissions left the extension unable to reach user-configured HTTPS backends because runtime fetch calls require host access.
  • The extension still allows arbitrary serverUrl values via the UI and config model, so a user-granted flow is needed to enable reachability for those origins without reintroducing broad static host permissions.

Description

  • Added optional_host_permissions with "https://*/*" to extension/manifest.json to enable runtime-granted host access via the Permissions API.
  • Implemented ensureHostPermission(serverUrl) in extension/popup.js and call it from applyServerForm, which derives the origin, checks chrome.permissions.contains, and requests origin-scoped access via chrome.permissions.request, throwing a clear error if denied.
  • Extended the test chrome mock in extension/tests/mocks/chrome.js with permissions.contains and permissions.request hooks so permission flows can be exercised deterministically.
  • Added integration tests in extension/tests/integration/popup.test.js to verify that applyServerForm requests the correct origin-scoped permission and fails when the user denies it.

Testing

  • Ran the updated popup integration tests with cd extension && npm test -- --run tests/integration/popup.test.js, and the suite passed (5/5 tests).
  • The permission request behavior is covered by the new tests which mock chrome.permissions.contains/request and assert correct calls and error handling.

Codex Task

Summary by Sourcery

Gate custom HTTPS backend usage behind runtime host-permission checks and user-granted origin access.

New Features:

  • Introduce runtime host-permission flow for user-configured HTTPS backends via a new ensureHostPermission helper in the popup form handler.

Bug Fixes:

  • Restore reachability of custom HTTPS backends by requesting origin-scoped host permissions instead of relying on broad static host permissions.

Enhancements:

  • Extend the Chrome mock with permissions APIs and add integration tests to cover permission request behavior in the popup form handler.

Tests:

  • Add integration tests ensuring applyServerForm requests the correct origin-scoped host permissions and fails when permissions are denied.

Copilot AI review requested due to automatic review settings May 4, 2026 02:36
@sourcery-ai

sourcery-ai Bot commented May 4, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Adds optional host permissions and a runtime permission flow so the extension can reach user-configured HTTPS backends, along with tests and mocks for the new permissions behavior.

Class diagram for popup module host permission logic

classDiagram
  class PopupModule {
    +applyServerForm(input)
  }

  class EnsureHostPermission {
    +ensureHostPermission(serverUrl)
  }

  class ChromePermissions {
    +contains(params)
    +request(params)
  }

  class ChromeRuntime {
    +sendMessage(message)
  }

  class ConfigRepository {
    +saveConfig(config)
  }

  PopupModule --> EnsureHostPermission : uses
  PopupModule --> ConfigRepository : calls_saveConfig
  PopupModule --> ChromeRuntime : sendMessage_CONFIG_UPDATED

  EnsureHostPermission --> ChromePermissions : contains_and_request

  note for PopupModule "Represents popup_js exported function applyServerForm"
  note for EnsureHostPermission "Encapsulates host permission checking and requesting before saving config"
Loading

File-Level Changes

Change Details Files
Introduce runtime host-permission request flow when saving a custom server URL.
  • Added ensureHostPermission(serverUrl) helper that normalizes the URL, derives an origin pattern, checks existing permissions, and conditionally requests origin-scoped access via chrome.permissions.
  • Updated applyServerForm to invoke ensureHostPermission before saving config and broadcasting CONFIG_UPDATED so misconfigured or denied permissions surface as errors.
extension/popup.js
Extend popup integration coverage to assert host-permission behavior for custom HTTPS backends.
  • Added tests to verify applyServerForm calls chrome.permissions.request with the correct origin pattern when host access is missing.
  • Added tests to verify applyServerForm rejects with a clear error when the permission request is denied.
extension/tests/integration/popup.test.js
Enable optional HTTPS host permissions in the extension manifest and wire up permissions mocks for testing.
  • Declared optional_host_permissions with "https:///" in the manifest to allow runtime-granted host access.
  • Refined manifest content_scripts formatting without functional changes.
  • Extended the chrome mock with permissions.contains and permissions.request implementations that default-grant localhost and web.whatsapp.com, and simulate a granted request by default.
extension/manifest.json
extension/tests/mocks/chrome.js

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • Consider restricting ensureHostPermission to only request permissions for https: URLs and/or explicitly skipping origins already covered by static host_permissions, to avoid unnecessary permission prompts for unsupported or already-allowed schemes.
  • It might be helpful to wrap the new URL(trimmed) call in ensureHostPermission with a try/catch and throw a more explicit configuration error, so we don’t rely on the generic URL parsing exception path for invalid serverUrl values.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider restricting `ensureHostPermission` to only request permissions for `https:` URLs and/or explicitly skipping origins already covered by static `host_permissions`, to avoid unnecessary permission prompts for unsupported or already-allowed schemes.
- It might be helpful to wrap the `new URL(trimmed)` call in `ensureHostPermission` with a try/catch and throw a more explicit configuration error, so we don’t rely on the generic `URL` parsing exception path for invalid `serverUrl` values.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e07afd8d4b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread extension/popup.js
Comment on lines +27 to 28
await ensureHostPermission(input.serverUrl);
await saveConfig({ serverUrl: input.serverUrl, apiKey: input.apiKey });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Validate server URL before requesting host permission

applyServerForm now calls ensureHostPermission before saveConfig, so parseable-but-invalid inputs (for example https://api.example.com/v1, which saveConfig rejects because only origin or /api paths are allowed) can still trigger and grant a host-permission prompt before the save fails. That leaves an unnecessary persistent permission on the extension even though the configuration was not accepted, which is both confusing and a permission-scope regression for users who mistype URLs.

Useful? React with 👍 / 👎.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Restores reachability to user-configured HTTPS backends by introducing runtime-granted host permissions, avoiding broad static host access while keeping the existing configurable serverUrl model.

Changes:

  • Added optional_host_permissions (https://*/*) to enable origin-scoped permission grants at runtime.
  • Added ensureHostPermission(serverUrl) and wired it into applyServerForm to request origin access when needed.
  • Extended the Chrome test mock and added integration tests covering permission request/deny flows.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
extension/manifest.json Adds optional HTTPS host permissions (and reformats content script arrays).
extension/popup.js Adds runtime permission check/request before saving server config.
extension/tests/mocks/chrome.js Adds chrome.permissions.contains/request to the test mock.
extension/tests/integration/popup.test.js Adds integration tests for requesting/denying host permissions on save.

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

Comment thread extension/popup.js
async function ensureHostPermission(serverUrl) {
const trimmed = String(serverUrl || '').trim();
if (!trimmed) return;
const u = new URL(trimmed);
Comment thread extension/popup.js
const u = new URL(trimmed);
const pattern = `${u.origin}/*`;
const has = await chrome.permissions.contains({ origins: [pattern] });
if (has) return;
Comment on lines +66 to +69
permissions: {
contains: vi.fn(async ({ origins }) => origins.every((origin) => origin.startsWith('http://localhost') || origin.startsWith('http://127.0.0.1') || origin.startsWith('https://web.whatsapp.com'))),
request: vi.fn(async () => true),
},
@DYAI2025 DYAI2025 merged commit d60ad26 into feat/extension-fix-and-hardening May 4, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants