Merge pull request #22 from outis1one/claude/read-repo-wA3y1

fix: ChatGPT interception — synchronous early fetch hook
This commit is contained in:
Outis
2026-03-27 00:29:00 -04:00
committed by GitHub
2 changed files with 36 additions and 4 deletions
+10 -3
View File
@@ -891,8 +891,11 @@
// ============================================================
// Fetch Interception — scans ALL POST requests with a body.
// Service-agnostic: doesn't depend on URL patterns.
// Uses __ssOriginalFetch from the early hook (injected synchronously
// before any page JS) to ensure we have the real fetch, even if
// frameworks like Next.js (ChatGPT) store a reference early.
// ============================================================
const originalFetch = window.fetch;
const originalFetch = window.__ssOriginalFetch || window.fetch;
// URLs to never touch (static assets, analytics, etc.)
const SKIP_URL_PATTERNS = [
@@ -1012,6 +1015,10 @@
return originalFetch.call(this, url, options);
};
// Register our fetch interceptor so the early hook proxy can use it
window.__ssInterceptFetch = window.fetch;
window.__ssReady = true;
// ============================================================
// Document Upload Processing
//
@@ -1376,8 +1383,8 @@
// ============================================================
// XMLHttpRequest Interception — same aggressive approach
// ============================================================
const origOpen = XMLHttpRequest.prototype.open;
const origSend = XMLHttpRequest.prototype.send;
const origOpen = window.__ssOriginalXHROpen || XMLHttpRequest.prototype.open;
const origSend = window.__ssOriginalXHRSend || XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.open = function (method, url, ...rest) {
this._ssUrl = url;
+26 -1
View File
@@ -70,7 +70,32 @@
// Merge active profiles into a flat identity object for the content script
const identity = mergeProfiles(identityData);
// Inject the main interception script into the page's world
// STEP 1: Inject a synchronous inline script that patches fetch/XHR
// IMMEDIATELY, before any page JS can store a reference to the originals.
// This thin proxy queues calls until the full content.js loads.
const earlyHook = document.createElement('script');
earlyHook.textContent = `(function(){
// Store the real fetch/XHR before any page script can
window.__ssOriginalFetch = window.fetch;
window.__ssOriginalXHROpen = XMLHttpRequest.prototype.open;
window.__ssOriginalXHRSend = XMLHttpRequest.prototype.send;
window.__ssReady = false;
window.__ssQueue = [];
// Replace fetch with a proxy that queues until content.js is ready
window.fetch = function() {
if (window.__ssReady && window.__ssInterceptFetch) {
return window.__ssInterceptFetch.apply(this, arguments);
}
// If not ready yet, call original (no substitution possible)
return window.__ssOriginalFetch.apply(this, arguments);
};
})();`;
(document.head || document.documentElement).appendChild(earlyHook);
earlyHook.remove();
// STEP 2: Load the full content.js which will use __ssOriginalFetch
// and set __ssReady = true when it's done hooking
const script = document.createElement('script');
script.setAttribute('data-ss-config', JSON.stringify({ mappings, identity, settings }));
script.src = api.runtime.getURL('src/content/content.js');