Browse Source

fix: hide GMxhr's response cookies from browser

fixes #1835
tophf 2 years ago
parent
commit
712df2b67a
2 changed files with 6 additions and 57 deletions
  1. 4 52
      src/background/utils/requests-core.js
  2. 2 5
      src/background/utils/requests.js

+ 4 - 52
src/background/utils/requests-core.js

@@ -47,20 +47,11 @@ const EXTRA_HEADERS = [
 const headersToInject = {};
 /** @param {chrome.webRequest.HttpHeader} header */
 const isVmVerify = header => header.name === VM_VERIFY;
-export const isCookie = header => /^cookie2?$/i.test(header.name);
+const isCookie = header => /^cookie2?$/i.test(header.name);
+const isntSetCookie = header => !/^set-cookie2?$/i.test(header.name);
 const isSendable = header => !isVmVerify(header)
   && !(/^origin$/i.test(header.name) && header.value === extensionOrigin);
 const isSendableAnon = header => isSendable(header) && !isCookie(header);
-const SET_COOKIE_RE = /^set-cookie2?$/i;
-const SET_COOKIE_VALUE_RE = re`
-  /^\s*  (?:__(Secure|Host)-)?  ([^=\s]+)  \s*=\s*  (")?  ([!#-+\--:<-[\]-~]*)  \3(.*)  /x`;
-const SET_COOKIE_ATTR_RE = re`
-  /\s*  ;?\s*  (\w+)  (?:= (")?  ([!#-+\--:<-[\]-~]*)  \2)?  /xy`;
-const SAME_SITE_MAP = {
-  strict: 'strict',
-  lax: 'lax',
-  none: 'no_restriction',
-};
 const API_EVENTS = {
   onBeforeSendHeaders: [
     onBeforeSendHeaders, 'requestHeaders', 'blocking', ...EXTRA_HEADERS,
@@ -71,20 +62,12 @@ const API_EVENTS = {
 };
 
 /** @param {chrome.webRequest.WebRequestHeadersDetails} details */
-function onHeadersReceived({ [kResponseHeaders]: headers, requestId, url }) {
+function onHeadersReceived({ [kResponseHeaders]: headers, requestId }) {
   const req = requests[verify[requestId]];
   if (req) {
-    // Hide Set-Cookie headers from the browser, and optionally set them in req.storeId
-    const { storeId } = req;
-    if (req.anonymous || storeId) {
-      headers = headers.filter(h => !SET_COOKIE_RE.test(h.name) || storeId && (
-        setCookieInStore(h.value, storeId, url),
-        false // overriding to allow declaring the function as `async`
-      ));
-    }
     // Populate responseHeaders for GM_xhr's `response`
     req[kResponseHeaders] = headers.map(encodeWebRequestHeader).join('');
-    return { [kResponseHeaders]: headers };
+    return { [kResponseHeaders]: headers.filter(isntSetCookie) };
   }
 }
 
@@ -114,37 +97,6 @@ function onBeforeSendHeaders({ requestHeaders: headers, requestId, url }) {
   return { requestHeaders: headers };
 }
 
-/**
- * @param {string} headerValue
- * @param {string} storeId
- * @param {string} url
- */
-function setCookieInStore(headerValue, storeId, url) {
-  let m = SET_COOKIE_VALUE_RE.exec(headerValue);
-  if (m) {
-    const [, prefix, name, , value, optStr] = m;
-    const opt = {};
-    const isHost = prefix === 'Host';
-    SET_COOKIE_ATTR_RE.lastIndex = 0;
-    while ((m = SET_COOKIE_ATTR_RE.exec(optStr))) {
-      opt[m[1].toLowerCase()] = m[3];
-    }
-    const sameSite = opt.sameSite?.toLowerCase();
-    browser.cookies.set({
-      url,
-      name,
-      value,
-      domain: isHost ? undefined : opt.domain,
-      expirationDate: Math.max(0, +new Date(opt['max-age'] * 1000 || opt.expires)) || undefined,
-      httpOnly: 'httponly' in opt,
-      path: isHost ? '/' : opt.path,
-      sameSite: SAME_SITE_MAP[sameSite],
-      secure: url.startsWith('https:') && (!!prefix || sameSite === 'none' || 'secure' in opt),
-      storeId,
-    });
-  }
-}
-
 export function toggleHeaderInjector(reqId, headers) {
   if (headers) {
     // Adding even if empty so that the toggle-off `if` runs just once even when called many times

+ 2 - 5
src/background/utils/requests.js

@@ -5,7 +5,7 @@ import ua from '@/common/ua';
 import cache from './cache';
 import { addPublicCommands, commands } from './message';
 import {
-  FORBIDDEN_HEADER_RE, VM_VERIFY, isCookie, requests, toggleHeaderInjector, verify,
+  FORBIDDEN_HEADER_RE, VM_VERIFY, requests, toggleHeaderInjector, verify,
 } from './requests-core';
 
 addPublicCommands({
@@ -189,7 +189,7 @@ async function httpRequest(opts, events, src, cb) {
   const [body, contentType] = decodeBody(opts.data);
   // Firefox doesn't send cookies, https://github.com/violentmonkey/violentmonkey/issues/606
   // Both Chrome & FF need explicit routing of cookies in containers or incognito
-  let shouldSendCookies = !anonymous && (incognito || IS_FIREFOX);
+  const shouldSendCookies = !anonymous && (incognito || IS_FIREFOX);
   xhr.open(opts.method || 'GET', url, true, opts.user || '', opts.password || '');
   xhr.setRequestHeader(VM_VERIFY, id);
   if (contentType) xhr.setRequestHeader('Content-Type', contentType);
@@ -199,9 +199,6 @@ async function httpRequest(opts, events, src, cb) {
     } else {
       xhr.setRequestHeader(name, value);
     }
-    if (shouldSendCookies && isCookie({ name })) {
-      shouldSendCookies = false;
-    }
   });
   xhr[kResponseType] = willStringifyBinaries && 'blob' || xhrType || 'text';
   xhr.timeout = Math.max(0, Math.min(0x7FFF_FFFF, opts.timeout)) || 0;