Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Override innerHTML throwing console errors #16

Open
dave-cunnington opened this issue Oct 3, 2024 · 2 comments
Open

Override innerHTML throwing console errors #16

dave-cunnington opened this issue Oct 3, 2024 · 2 comments

Comments

@dave-cunnington
Copy link

After updating to version 1.2.2 we started getting console errors in the overwritten innerHTML code, specifically replace() on a null object.

no-unsafe-inline-fix…le.js?ver=1.2.2:381 Uncaught (in promise) TypeError: replaced.replace is not a function at HTMLSpanElement.set [as innerHTML] (no-unsafe-inline-fix…js?ver=1.2.2:381:25) at _.nf (main.js:90:236) at _.KE (util.js:67:356) at dM (controls.js:67:410) at new mMa (controls.js:163:804) at nMa (controls.js:67:264) at new TMa (controls.js:165:422) at VMa (controls.js:85:25) at new RNa (controls.js:182:365) at AOa.SNa [as xJ] (controls.js:111:161)

@MocioF
Copy link
Owner

MocioF commented Oct 3, 2024

Hi @dave-cunnington, I need to know what scripts you are using in your pages. Overriding native functions is (almost always) a bad idea, but there is no other way to deal with js frameworks that append inline styles to the DOM (and this is why we need to override those functions). This behavior, however, can be disabled with the specific setting in the option page.
However, can you point me to the page where you are collecting this error?

@jkirrane
Copy link
Contributor

@MocioF I ran into this same issue this week with a Recaptcha V3 script in Chrome. The Recaptcha script updates innerhtml but it uses the TrustedHTML interface of the Trusted Types API so the nunilMaybeSetStyleNonce function fails since the e object does not have a replace() method.

I was not aware of the setting in the option page you referenced above, so I updated the no-unsafe-inline-fix-style.min.js file in the following way:

var OriginalSet = Object.getOwnPropertyDescriptor(Element.prototype, 'innerHTML');
Object.defineProperty(Element.prototype, "innerHTML", {
    set: function(e) {
        if (typeof e !== 'string') {
            OriginalSet.set.call(this, e);
        } else {
            e = (e = nunilMaybeSetLinkIntegrity(e = nunilMaybeSetScriptIntegrity(e = nunilMaybeSetScriptNonce(e = nunilMaybeSetLinkNonce(e = nunilMaybeSetStyleNonce(e)))))).replace(/\bstyle=/gim, "data-style-nunil-inh="),
            innerHTMLSetter_.call(this, e),
            requestAnimationFrame( () => {
                nunilParseArgToStyle("data-style-nunil-inh")
            }
            )
        }
    }
});

This allows non string objects to use the default setter function and to only use your custom setter if e is a string. This has fixed the problem for me and not introduced any new ones.

Do you think this is an appropriate solution? I can generate a PR if so.

Can you provide more information about how the behavior "can be disabled with the specific setting in the option page"?

For further info, this is the link to the Recaptcha script: https://www.gstatic.com/recaptcha/releases/rW64dpMGAGrjU7JJQr9xxPl8/recaptcha__en.js

Here is the section of that script that sets the innerhtml:

        function(x, F, J, n, W, H, v, k, U, y, e, a, C) {
            if (!(C = ["X", 29, 27],
            (x | 5) >> 4)) {
                a: {
                    if ((H = (k = F(J || qb, n),
                    W) || w[20](4),
                    k && k.Z) ? y = k.Z() : (y = H.createElement("DIV"),
                    v = M[16](5, ">", k),
                    y.innerHTML = Y[47](16, "", v)), // <-- innerhtml set here
                    y.childNodes.length == 1 && (U = y.firstChild,
                    U.nodeType == 1)) {
                        e = U;
                        break a
                    }
                    e = y
                }
                a = e
            }
            if ((x | 24) == x) {
                if (typeof F === "function")
                    n && (F = Wp(F, n));
                else if (F && typeof F.handleEvent == "function")
                    F = Wp(F.handleEvent, F);
                else
                    throw Error("Invalid listener argument");
                a = Number(J) > 2147483647 ? -1 : Vj.setTimeout(F, J || 0)
            }
            if ((x >> 1 & 11) == 3) {
                (v = (n = n === void 0 ? J.LW() : n,
                {}),
                J)[C[0]] || (J[C[0]] = p[46](32));
                try {
                    H = (new URL(J[C[0]])).toString()
                } catch (I) {
                    H = (new URL(J[C[0]],w[32](14).location.origin)).toString()
                }
                a = ((W = new URL(H),
                n) && (v.Authorization = n),
                J.fW && (v["X-Goog-AuthUser"] = J.fW,
                W.searchParams.set("authuser", J.fW)),
                {
                    url: W.toString(),
                    body: F,
                    Gs: 1,
                    PV: v,
                    ue: "POST",
                    withCredentials: J.withCredentials,
                    eQ: J.eQ
                })
            }
            return (((x + 3 & 16) < 4 && (x << 1 & C[1]) >= 13 && O.call(this, F, 0, "patresp"),
            x) | 80) == x && (V[15](8, v9, F) || V[15](9, Q4, F) ? W = String(F).replace(kv, M[49].bind(null, C[2])) : (F instanceof $R ? J = String(B[42](16, F).toString()).replace(kv, M[49].bind(null, C[1])) : (n = String(F),
            J = EL.test(n) ? n.replace(kv, M[49].bind(null, 30)) : "about:invalid#zSoyz"),
            W = J),
            a = W),
            a
        }

Elsewhere in that script you can see where it creates the Trusted Types policy, as far as I can tell:

                        n = JG.createPolicy(FZ, {
                            createHTML: J,
                            createScript: J,
                            createScriptURL: J
                        })

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants