Audit Chrome Extension Network Requests
How to Review Network Calls in Extension Source
Follow outbound calls from their inputs to their destinations, then check what the browser actually sends.
Search for fetch, XHR, and remote domains
Get the public ZIP through CRXFile and extract it. Keep its version with your notes. Our source inspection guide covers that first pass. In an editor, search across JavaScript and HTML, including bundled files. With ripgrep installed, this command gives you a starting list:
rg -n -i 'fetch\s*\(|XMLHttpRequest|axios|https?://|wss?://|sendBeacon|WebSocket' .Follow the matches. fetch may sit behind a wrapper called apiClient. Our example below calls an injected fetcher, so searching only for fetch( would miss that call. Look for XMLHttpRequest, including its open() and send() calls. Chrome's worker migration guide notes that XHR isn't available inside service workers, but you may find it in extension pages or older background code.
Don't count every URL as an upload. A license comment or documentation link doesn't make a request. And an empty result proves little: aliases, encoded strings, computed URLs, or a different transport can hide from this literal search. Check HTML resource URLs and CSS imports too.
Identify the execution context and host access
Find whether the call runs in a content script, popup, or extension worker. Chrome's cross-origin request guide explains the difference: worker and extension-page cross-origin fetches need suitable host permissions, while content scripts remain subject to the page's cross-origin restrictions. Adding a host grant doesn't remove that content-script boundary.
Compare the endpoint with host_permissions and optional_host_permissions. A declaration doesn't prove the user granted it or that a call happened. Our extension permissions guide helps separate requested access from current grants. Chrome's permission documentation lists the relevant manifest fields.
Read one complete request, including its body
Here's our original request.js example. It's a standalone teaching module, not a complete installable extension. The optional third argument lets the check page replace fetch with a mock:
// Original CRXFile teaching example. MIT License (see repository LICENSE).
export async function sendTitleForReview(pageUrl, title, fetcher = fetch) {
const page = new URL(pageUrl);
if (page.protocol !== "https:" || typeof title !== "string" || title.length > 120) {
throw new TypeError("Expected an HTTPS URL and a title of at most 120 characters.");
}
const endpoint = "https://collector.example/v1/review";
const response = await fetcher(endpoint, {
method: "POST",
headers: { "Content-Type": "application/json" },
credentials: "omit",
redirect: "error",
body: JSON.stringify({ origin: page.origin, title })
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
return response.status;
}Start at the inputs. The function accepts an HTTPS page URL and a string title of at most 120 characters. It extracts the page's origin, then sends that origin and the title as JSON to a fixed endpoint. The page path, query string, and fragment don't enter this body. The title still does, and titles can contain private information.
credentials: "omit" excludes credentials such as cookies from this fetch; it doesn't remove data placed in JSON. The function also rejects redirects and checks response.ok. Fetch doesn't automatically reject an HTTP 503 response. See MDN's Fetch API guide for credentials and HTTP error handling.
Check the URL as carefully as the body. A GET request can carry data in query parameters, even without JSON. Follow URLSearchParams or string concatenation back to its inputs. In another package, an identifier might come from storage rather than the current page.
Build a network request review table
Use one row per question, then repeat the review for each call site. These are source findings for our example, before any real network test:
| Check | Evidence in request.js | Follow-up |
|---|---|---|
| Trigger | Exported sendTitleForReview function | Find its caller and event. |
| Destination | https://collector.example/v1/review | Check configuration and redirects elsewhere. |
| Payload | POST JSON: origin and title | Trace where each argument originates. |
| Credentials | omit; no Authorization header | Check other request headers and identifiers. |
| Failure | Throws on invalid input or non-OK status | Inspect caller retries and error reporting. |
Reproduce the payload with a mocked fetch
Open the browser mock check and click “Run mocked request.” The valid case captures one POST with origin: "https://example.com" and title: "Demo account". Compare it with the longer input URL shown below the controls.
Choose the HTTP-page case or the overlong title. Both should stop before fetch. The simulated 503 case should record one call and report an error. The check runs the same module printed above and always supplies a mock. It sends no collector POST and doesn't verify CORS or extension permissions. You can inspect the request shape without installing an extension.
Follow messages into the network caller
A content script can hand page data to a worker that makes the request. Search for its message type and find the receiving listener, then follow the payload into the network helper. Check who can send that message and whether the receiver restricts destinations. Chrome's messaging guide describes these connections. Our service worker walkthrough shows how to trace the receiving handler.
Read the caller's error branch too. A retry loop can send the same payload repeatedly, and a saved queue may send it after the original page closes. Record when the caller retries and what clears queued data. That behavior won't appear in the helper's request options.
Compare the source trace with DevTools
For a trusted extension you already run, open DevTools for the component making the call. Start recording before you trigger the feature. Select the request and compare its URL, method, payload, and response status with your notes. Follow Initiator to the calling code. Chrome's Network panel reference covers those views. A page's Network panel alone can miss work in the extension worker or popup.
Record the version and the action you tested. No observed request means only that you didn't capture one during that test. A feature might wait for a login, an alarm, or another permission grant. Keep the unresolved trigger or destination in your review notes so the next test has a specific question to answer.