Skip to content

Inconsistent GM_cookie.set behavior across browsers when used with GM_xhr and WebSocket #2721

@Qwyua

Description

@Qwyua

Background

I wasn’t sure whether to open an issue or not. Even though I suspect the problem might be related to browsers, I felt it was necessary to ask in order to clarify the situation and understand what is actually happening.

Before opening this issue, I reviewed the discussions in the following sources. I’m grateful to the users who shared information there:

Problem

Trying to open a WebSocket connection to a specific domain from a website that belongs to a different domain. However, getting different results across different browsers.

Question

What I would mainly like to understand is whether this behavior is caused by the Tampermonkey extension itself or if it is a browser-related limitation or security behavior. Clarifying this would help me understand the situation much better.

Tampermonkey Version 5.4.1 Browsers tested:

  • Google Chrome
  • Microsoft Edge
  • Firefox
Browser Mode Cookie 1 Cookie 2 WebSocket Status
Chrome Normal Failed
Chrome Incognito Failed
Edge Normal Success
Edge InPrivate Failed
Firefox Normal Partial
Firefox Private Partial

A script sets two cookies using GM_cookie.set, performs a request using GM.xmlHttpRequest, and then opens a WebSocket connection that relies on those cookies for authentication.

The WebSocket connection works only if both cookies are correctly applied.

However, the behavior differs depending on the browser.

if(location.href.includes("https://example.com")) return;

GM.xmlHttpRequest({
    method: "GET",
    url: "https://example.com/getServerCookie?verify=1",
    withCredentials: true,
    cookiePartition: {topLevelSite:location.origin},
    onloadend:r=>{
        let readyCount = 0;
        const [cookie1Value,cookie2Value]=[/cookie1=([^;\r\n]+)/i,/cookie2=([^;]+)/i].map(x=>r.responseHeaders.match(x)?.[1]??false);

        const tryOpenWebSocket = () => {
            if (readyCount !== 2) return;

            GM_cookie.list({ url: "https://example.com" }, (cookies, error) => {
                if (error) return console.error("Cookie list error:", error);
                if (!(cookies.some(c => c.name === "cookie1") && cookies.some(c => c.name === "cookie2"))) {
                    return console.warn("Not all cookies are set yet:", cookies);
                }

                const ws = new WebSocket("wss://server.example.com/socket");
                ws.onopen = () => console.log("WebSocket opened (Partial)");
                ws.onerror = e => console.error("Failed");
                ws.onmessage = e => e.data === 'welcome' && console.log("Success!");
            });
        };


        cookie1Value && GM_cookie.set({
            url: `https://example.com`,
            name: "cookie1",
            value: cookie1Value,
            domain: `.example.com`,
            path: "/",
            secure: true,
            httpOnly: false,
            sameSite: "no_restriction"
        },e=>!e&&(readyCount++,tryOpenWebSocket()));

        cookie2Value && GM_cookie.set({
            url: `https://example.com`,
            name: "cookie2",
            value: cookie2Value,
            domain: `.example.com`,
            path: "/",
            secure: true,
            httpOnly: false,
            sameSite: "no_restriction"
        },e=>!e&&(readyCount++,tryOpenWebSocket()));
    }
});

Honestly, I didn’t notice the issue until some script users reported that it wasn’t working, because I was using Edge… Anyway, for now, it seems like my only option is to direct users to Edge.

P.S.: The script has nothing to do with example.com; it was chosen solely to help issue readers visualize the userscript. Love you, example.com!

Testing Environment

All tests were performed under the same environment and conditions. Below are the reference screenshots:

Image
Image
Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions