kylepaulsen / ResourceOverride

An extension to help you gain full control of any website by redirecting traffic, replacing, editing, or inserting new content.
MIT License
467 stars 117 forks source link

Implemented a workaround for subresource integrity. #45

Open KOLANICH opened 3 years ago

KOLANICH commented 3 years ago

Had to do a very little bit of refactoring.

The changes consist of 2 parts.

  1. Runtime integrity removal.

We use Mutation events (which will likely be removed somewhen in future, but I hope not) to remove integrity attributes from elements having them.

Mutation observers cannot replace them, since they by design have no capturing mode (this was the main point of their introduction), so they always see the changes after they have already happenned (and so don't delay them happening). For us it means that when an element is added, the request is sent immediately, and its result is checked and we have no influence on this. To implement an observer-compatible impl we probably should block the first request to fail fast, then drop the integrity attr, then redo the request. Unfortunately it seems we cannot bind a HTML element to request.

Mutation observers set up early catch even nodes created by HTML renderer in process of page load.

Mutation events allow capturing (and so slow-down everything untill the hanler ends), so we try to use them, if they are available. Unfortunately, they don't catch nodes created by a HTML renderer.

So, the next component of the impl.

We use blocking WebRequest to patch HTML on the fly. This will work only for Firefox, Google doesn't want us to mess with their malware on the fly. We do it only to the requests with content type text/html. Content of all the other is not modified.

The API is designed to wkrk on chunks to process data chunk-by-chunk. Nice for stream cyphers, but we don't work on this low level since browsers lack API and abstractions for doing that ( a. a stream of bytes object for which Browser will work b. a decoder that can consume a stream of bytes and generate a stream of bytes c. a HTML parser that can consume a stream of bytes and generate a stream of SAX-like events manipulating DOM ).

So I have written a function to combine the chunks into 1 Uint8Array, that returns a promise (since the interface is event-driven).

Then we try to parse it into HTML DOM. First we parse with ASCII encoding, get the right charset from HTML itself, then parse using the specified encoding.

After that we process the DOM,remove all the integrity nodes, then serialize and encode back.

It is slow, but I guess not much than doing this using scripts for Fiddler (a local proxy for debugging and messing with apps using HTML) or mitmproxy.

For controlling GUI has been implemented. An additional rule that has only a param of URI to be overridden.

This PR is kinda a draft since integrity removal on a page is not yet controlled. I'd like to remove integrity to only overridden resources.

@kylepaulsen, what do you think?

kylepaulsen commented 3 years ago

I appreciate your dedication, however is this fixing a bug? This seems like a feature to me. I don't really have time to test and support new features for Resource Override at this time. Additionally, if chrome is going to deprecate manifest version 2 at some point then this extension is dead as their new api isn't compatible with the matching system this uses. I suppose we could use their new matching system but that means everyone would have to remake their rules. Also maybe it wouldn't be "dead" to firefox.. I dunno.

Anyway yeah, sorry, I just got too many other things going on right now. You are perfectly welcome to publish your own extension and use this code as it's under MIT.

KOLANICH commented 3 years ago

is this fixing a bug? This seems like a feature to me.

Yeah, it is a feature, fixing a bug, that RO cannot be used for resources with integrity ;) First I looked for an about:config pref for it, but haven't found.

Additionally, if chrome is going to deprecate manifest version 2 at some point then this extension is dead as their new api isn't compatible with the matching system this uses.

  1. Firefox currently is not going to drop that. (But I feel like Firefox won't exist long).
  2. Brave is not going too. But I'm not sure that Brave has all the API needed. I usually use only Firefox.

You are perfectly welcome to publish your own extension and use this code as it's under MIT.

I don't want to be a maintainer. I have too lot of projects I maintain, so I even had to split non-fork repos of my GH account into multiple orgs.

Maybe someone of watchers can help?