Is ChiliCal Co-Pilot: Smart Scheduling Links safe?

High risk

ChiliCal Co-Pilot: Smart Scheduling Links is high risk. The extension requests tab and scripting permissions, runs a content script on every HTTPS page, and its worker enumerates tabs before injecting scripts. This can expose tab URLs/titles; the all-pages script gets DOM access site-wide.…

google-marketplace-chili-piperv2.0.220Chrome Web Store
75Risk

AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.

Publishers can request a review.

Findings

SeverityMEDIUM
ClassUNWANTED
TypeUnexpected
CWECWE-200
SourceAI SANDBOX

Broad site access exposes tabs and page context

The extension requests tab and scripting permissions, runs a content script on every HTTPS page, and its worker enumerates tabs before injecting scripts.

This can expose tab URLs/titles; the all-pages script gets DOM access site-wide.

01EvidenceCAUSE EFFECT
What actually happens
You did this

You browse to an HTTPS page or install the extension while tabs are already open.

The manifest rule covers every HTTPS hostname, not only Gmail, Calendar, Chili Piper, or CRM domains.

The extension did this

The extension can load its all-pages script and enumerate open tabs in the current window.

The background code reads tab objects and conditionally injects scripts based on the manifest rules.

02EvidenceFIELD TABLE
Fields and surfaces available through the broad site and tab access
FieldValueWhy it matters
Every HTTPS page
https://*/* -> assets/all-pages.tsx-loader-OGCbNNgF.jsLets the extension run code on ordinary HTTPS websites, not just the scheduling and CRM sites named by its workflow.
Open-tab URL
https://calendar.google.com/calendar/u/0/r/week/2026/7/14 (illustrative)Shows the exact website and path open in a browser tab.
Open-tab title
Q3 Account Plan - Google Docs (illustrative)Can reveal the page or document name shown in a tab.
Closed-tab record
{"taskTitle":"Follow-up meeting","time":"2026-07-14T10:24:18.000Z","tabs":[{"id":132,"url":"https://docs.google.com/document/d/1R9cAccountPlan/edit","title":"Q3 Account Plan - Google Docs"}]} (illustrative)Preserves tab details when the external close-tabs path runs.
Page DOM context
document_start on https://example.com/account/settings (illustrative)Lets the content script interact with page text and controls wherever it is injected.
03EvidenceTEMPORAL PATTERN
When this fires
On every browser startup

On extension install, the service worker walks the current window and executes matching content scripts into open tabs.

04EvidenceCODE COMPARE
The code that does this

All-pages content script loads on the manifest-wide HTTPS rule

What it actually does
Readable all-pages loaderassets/all-pages.tsx-loader-OGCbNNgF.js
(function () {
  'use strict';

  const injectTime = performance.now();
  (async () => {
    const { onExecute } = await import(
      /* @vite-ignore */
      chrome.runtime.getURL("assets/all-pages.tsx-CGU5-oKu.js")
    );
    onExecute?.({ perf: { injectTime, loadTime: performance.now() - injectTime } });
  })().catch(console.error);

})();
Readable all-pages moduleassets/all-pages.tsx-CGU5-oKu.js
import "./dom-CqbklTiD.js";
import {
  V as r
} from "./storage-BtmlRvgS.js";
import {
  e as s,
  t as a,
  r as m,
  m as c,
  n as p,
  o as d
} from "./kosmotime-CuYXStFD.js";
import {
  c as l,
  t as f
} from "./window-dbulYq-M.js";
import {
  a as u,
  h
} from "./helpers-BeJRVsM0.js";
import "./_commonjsHelpers-BosuxZz1.js";
import "./availability-CjK9m9ja.js";
import "./onboarding-gUMWqHup.js";
import "./window-Cnt40wQZ.js";
import "./LabelToggle-B8AIzypx.js";
import "./isDefined-3JP48FH8.js";
import "./ChiliPiper-D2OuC778.js";
document.addEventListener("keydown", function(i) {
  i.key === "Escape" && (s(), l())
});
chrome.runtime.onMessage.addListener(i => {
  i.type === "LOGIN" && i.value && r.setToken(i.value), i.type === "TOGGLE_COMMAND_CENTER" && a(), i.type === "TOGGLE_SIDEBAR" && f(), i.type === "INIT_ONBOARDING" && u()
});
const N = async () => {
  if (!["chilipiper.io", "chilipiper.com"].some(o => window.location.hostname.includes(o))) try {
    const o = await c();
    if ((o == null ? void 0 : o.type) === "Running") {
      const t = await p(),
        n = t == null ? void 0 : t.some(e => e.id === o.session.taskId);
      t && t.length > 0 && n && d(t[0].id)
    }
  } catch (o) {
    console.debug("Could not check for running session", o)
  }
};
m("fire-browser-extension");
N();
chrome.runtime.sendMessage({
  type: "CONTEXT_READY"
}, i => {
  (i == null ? void 0 : i.type) === "postInstallPending" && h()
});
05EvidenceCODE COMPARE
The code that does this

Background code enumerates tabs and executes matched scripts

What it actually does
Readable matcher and install-time injectorassets/background.ts-CymZiZHH.js
  mt = (a, r) => {
    const t = a.replace(/https?:\/\/([a-z0-9-]+)\./i, "https://*."),
      e = [a, t];
    return r.filter(i => {
      var h;
      return (h = i.matches) == null ? void 0 : h.some(d => {
        if (d === '"https://*/*"') return !0;
        const g = d.replace(/\/\*$/, "");
        return e.some(o => o == null ? void 0 : o.includes(g))
      })
    })
  },
  St = () => {
    const a = {
        currentWindow: !0
      },
      r = chrome.runtime.getManifest().content_scripts || [];
    chrome.tabs.query(a, function(t) {
      t.forEach(e => {
        if (e.url) {
          const s = mt(e.url, r);
          s == null || s.forEach(i => {
            chrome.scripting.executeScript({
              target: {
                tabId: e.id
              },
              files: i.js ?? []
            }).catch(console.error)
          })
        }
      })
    })
  };
chrome.runtime.onInstalled.addListener(async a => {
  a.reason === chrome.runtime.OnInstalledReason.INSTALL && (v = !0, St())
});
Readable external-message tab handlingassets/background.ts-CymZiZHH.js
chrome.runtime.onMessageExternal.addListener(a => {
  if (a.type === "CLOSE_TABS") return chrome.tabs.query({
    currentWindow: !0
  }, r => {
    const t = r.filter(e => !e.active).filter(e => !yt(e));
    if (t.length > 0) {
      const e = G(),
        s = new Date,
        i = a.taskTitle,
        h = t.map(d => d.id).filter(E);
      chrome.tabs.remove(h), $.getKey("CLOSED_TABS").then(d => {
        const g = {
            [e]: {
              tabs: t,
              taskTitle: i,
              time: s.toISOString()
            }
          },
          o = d ? {
            ...d,
            ...g
          } : g;
        $.setKey("CLOSED_TABS", o).then(() => {
          chrome.tabs.create({
            url: chrome.runtime.getURL("src/app/close-tabs/close-tabs.html")
          }).catch(console.error)
        }).catch(console.error)
      }).catch(console.error)
    }
  }), !0;
  a.type === "LOGIN" && (l().setKey("JWT_TOKEN", a.value), l().setKey("LOGIN_STATUS", "success")), a.type === "LOGOUT" && (l().removeKey("JWT_TOKEN"), l().setKey("LOGIN_STATUS", "idle")), chrome.tabs.query({
    currentWindow: !0
  }, r => (r.forEach(t => {
    t != null && t.id && chrome.tabs.sendMessage(t.id, {
      ...a
    }).catch(console.error)
  }), !0))
});
Updated 17 September 2026chngjgginikejcpaejphfoglpppmjfne