Issue description

Chrome Version : 21.0.1148.0
What steps will reproduce the problem?
1. Create an extension with "webRequest" and "*://*/*" host permissions.
2. Add listener to "chrome.webRequest.onBeforeRequest" in extension's code.
3. Open new tab and perform a WebSocket request to any URL.
What is the expected result?
Listener intercepts request.
What happens instead?
Request is sent without interception.
Please provide any additional information below. Attach a screenshot ifpossible.
Also, it seems that "ws://" and "wss://" schemes per se are not supported in "permissions" property in application manifest, same as in "urls" property in RequestFilter object. The extension described above intercepts other (non-WebSocket) types of requests as expected.

The usual support for policy based URL blacklists is in ChromeNetworkDelegate::OnBeforeURLRequest, which is shared to be used by the WebRequest API and the policy based URL blacklists.
My point was that once we support the webRequest API for web sockets, we should also have a shared place to do policy based blacklisting and webRequest API based cancelling.

Yes, exactly. Mike received some external reports that are asking for this. I saw that Adam is the current owner and according to his teams page working on a new Web Sockets stack. So I was wondering whether the problem solves itself automatically. Otherwise, we should see what's necessary to get there.

Right. Old WebSocket stack doesn't use net::URLRequest to issue an opening handshake. OnBeforeRequest() hook of ExtensionWebRequestEventRouter is invoked in the ChromeNetworkDelegate. Events on URLRequest are intercepted by NetworkDelegate but SocketStream events are not.
The new stack uses the URLRequest.

I think there are three levels of extension support we could add:
1. Basic interception of WebSocket handshakes, similar to HTTP. We probably should have this, but I don't know how to implement it. Maybe it should be opt-in, so that extensions which up until now haven't seen WebSocket requests don't accidentally start blocking them all?
2. Interception of data frames sent to/from the renderer. This would involve a brand new extension API. I don't know what the use-case would be.
3. The ability to implement WebSocket extensions in Chrome extensions. This would be prohibitively complex.

I think option 1 should be fine. That is basically what Firefox does. And would be sufficient for us - Adblock Plus. However, excluding WebSocket requests by default isn't necessary IMO. For example if an extension is blocking all kind kind of requests to example.com, blocking WebSocket requests as well is probably the intended the behavior. And on the other hand if an extension only considers certain request types, it will just ignore WebSocket requests anyway, assuming there will be a new type indicating WebSocket requests.

I'm also in support of option 1. Like #32, I support opt-out and not opt-in.
There are badware distributors "exploiting" (using the lack of implementation reflected in this bug) this to distribute potentially dangerous code to clients already.

Upping priority to P2 due to active exploitation report from #34. It appears that fixing this may be as simple as changing HasWebRequestScheme() in //extensions/browser/api/web_request/web_request_permissions.cc but verification is needed (and there ought to be a test to make sure it keeps working).

orangewi...@gmail.com said:
There are badware distributors "exploiting" (using the lack of implementation reflected in this bug) this to distribute potentially dangerous code to clients already.
Does anyone know an example of this exploit?
Maybe people will notice when real exploit happens in the wild

@48 precisely.
The failure to implement websocket intercepts means malvertising has an unimpeded path into our browsers.
I know this bug is tagged privacy, but it's a serious security flaw given how popular it is to breach advertising networks for the purpose of distributing malvertising on large, popular websites.

> they replace the WebSocket API with dummy code
There is no dummy code, it's wrapper code, which purpose is to allow uBO to become aware of WebSocket creation while keeping the functionality of WebSocket when they are not to be filtered.

Whether it is dummy code or wrapper code, they are bad because of chrome's multi-thread multi-process way.
If there is just a slight delay (eg due to a background process doing something), chrome may skip whatever the extension is trying to do or it will be inserted and executed too late meaning the script that use websockets have already been executed.
People have been talking about before-script-execution event and similar to try and solve this issue. Chrome dev team doesn't want to play ball as usual. It must be their motto: "We will not be co-operative at all!".

From comment #35, this looks like a fairly simple fix.
>>> Upping priority to P2 due to active exploitation report from #34. It appears that fixing this may be as simple as changing HasWebRequestScheme() in //extensions/browser/api/web_request/web_request_permissions.cc but verification is needed (and there ought to be a test to make sure it keeps working).
Can anyone from Chrome team verify this assessment?

This loophole has already been used by an advert network (revdefender) to deliver advert or anti-adblock scripts.
It won't be long before malware starts using this vulnerability. Only then this issue will be acknowledged as a security problem.
I hope this will be fixed before too many people get hurt.

#57: It's not a security problem for Ad networks to use javascript functions to deliver ads.
Malware that exploits security vulnerabilities in browsers should be addressed at the root, not by breaking core Javascript functionality.
uBlock Origin, Adblock Plus, etc., are breaking core JS functionality and presenting even more security issues by overriding basic JS functions.
It would be prudent for Chrome to implement a fine-grained permission model to allow or disallow extensions from overwriting core JS functionality so users can make informed decisions.
The adblock extensions which overwrite WebSocket() may introduce their own security issues or break other things and the user will almost certainly believe it to be the browser's fault.

Adverts are a well documented vector for serving malware. That even has a name "malvertising" https://en.wikipedia.org/wiki/Malvertising . To say that an open source wrapper for the WebSocket function is more of a security risk than these adverts seems crazy to me. (Of course I will be happy when the warppers are no longer required, but I'm not holding my breath there...)

#58: While we're at it, how about a fine-grained permission model for what third-party domains the browser can connect to using what technologies, so that these kind of problems can be solved at the root if need be?
And I strongly disagree with your notion that there is only one point at which malware problems need to be solved. Content blockers *already* let the user make an informed decision, and they are an important tool in preventing the spread of malware, *even* if you discard the other reasons for blocking ads (such as not consenting to being manipulated).

routeh is working in advertising industry:
"I am recovering over $1,000,000 / quarter in lost revenue from Adblock for my current employer. I have designed and implemented multiple strategies to combat Adblock."
yep, he's crazy.

> and the user will almost certainly believe it to be the browser's fault.
And the best part here: it actually will be "the browser's fault"! 'Cause if someone will manage to break through browser's security using wrapped around WS he will manage to do so without that wrapper at all.
...also, WS is not part of "core Javascript functionality".

https://tools.ietf.org/html/rfc6455
WebSockets are core functionality. Overwriting them without informing the user is unsafe.
Once upon a time, Android apps could be installed with a very coarse permission model. Now, many individual items require user input approval.
It would make sense to adopt this same permission model for Chrome and Extensions, so users can make informed decisions about the extensions they're installing.
What would stop a malicious extension from intercepting WebSockets requests, copying the data and sending it to a logging server? How would you know?
How can non-technical users understand the risks presented to them from extensions which overwrite Websockets and perform their own logic on top?

I see, the advertising industry (the very dark part of this "industry") is very angry: they wont be able anymore to deliver malware using websockets.
What about the malicious ads / popups plenty of pages are trying to deliver to so-called non-technical users ? Are you also worried about them ?

> WebSockets are core functionality.
Nope, also you gave a link to WebSocket Protocol, not WebSocket object. JS have a couple of fundamental objects and WS is not one of these.
> What would stop a malicious extension from intercepting WebSockets requests, copying the data and sending it to a logging server? How would you know?
What would stop malicious extension from stealing your credit card data and show you third-party ads? If extension already have access to the page it can do whatever it want and rewriting WS is just a tiny fraction of that. You can modify the entire page as you wish, so malicious extension can simply add necessary code into the page scripts on the fly. It can log every your keystroke within a page and every single click. Some banks have a special on-screen keyboard with randomized button locations, but malicious extension can detect where you clicked and which number was that. So, separate permission for redefining stuff like WS won't help anyone and only add the confusion.

#63: It is very telling that you are conveniently glossing over the problem of ability-to-block-ads, focusing on lobbying for removal of *current means* for doing that instead, despite that not being what this thread is about *at all*.
This is made even more questionable by the fact that you are employed at Mindgeek *specifically* in a role where you are responsible for *preventing ad-blocking*. You are evidently here to try and protect your business, rather than to argue security.
But I'll briefly entertain your question:
> What would stop a malicious extension from intercepting WebSockets requests, copying the data and sending it to a logging server? How would you know?
Nothing. Just like for any other kind of software. Just like for scripts loaded on the page. I'm all for more granular permission models, but that's not what you're here to argue. You're trying to get the ability to block ads removed.
If you *truly* feel that there needs to be a more granular permission model for extensions, then please create your own issue on the Chromium tracker to argue that, and stop hijacking this one for your own interests.

Pornhub and many other adult sites ("Pornhub") are owned by MindGeek[1].
These sites currently deliver 3rd-party ads (including 3rd-party javascript code) through WebSocket connections.
In Chromium-based browsers, WebSocket requests do not go through the webRequest API (the present issue). So they can't be blocked, in practice they are "invisible" to an extension.
A blocker wrapping WebSocket on a Chromium-based browser gain the ability to block WebSocket-based ads served by Pornhub.
uBlock Origin ("uBO") currently does this through its companion extension uBO-WebSocket. uBO-WebSocket still has a relatively small user base.
The next version of Adblock Plus ("ABP") and AdBlock (which uses ABP's filtering engine) will gain the ability to block WebSocket's connections through wrapping.[2]
Adblock Plus + AdBlock together have tens of millions of users.
This is of course what really worries #58 -- only this can explain the nonsensical arguments put forth.
1. https://en.wikipedia.org/wiki/MindGeek#Adult_industry
2. https://issues.adblockplus.org/ticket/1727

Correction:
> A blocker wrapping WebSocket on a Chromium-based browser gain the ability to block WebSocket-based ads served by Pornhub.
Should really be:
> A blocker wrapping WebSocket on a Chromium-based browser gain the ability to disclose to the user, and to block WebSocket-based connections made by web pages served by Pornhub.
The ability to even just disclose to users these previously invisible connections is a big pro-users forward step.

yes, the wording is a bit confusing here.
Actually, in comment #67, he said that:
In Chromium-based browsers, WebSocket requests do not go through the webRequest API (the present issue). So they can't be blocked, in practice they are "invisible" to an extension.

For book keeping, Chromium team has merged in to this ticket:
https://bugs.chromium.org/p/chromium/issues/detail?id=362351
After reading this:
https://issues.adblockplus.org/ticket/4372
There appears to be a strong motivation on the extension side to ensure they can blacklist / whitelist network calls. As a for-profit organization, I believe the only reason for this is for them to further profit from "Acceptable" programmes, similar to "Acceptable Ads".
I can see an offering in the future for "Acceptable WebSockets", "Acceptable WebRTC", etc.

#72: Please cut out the nonsense in this thread. The majority of content-blocking extensions are not commercial at all, and have no such programmes.
If you have a problem with AdBlock Plus or their Acceptable Ads programme, then take up the issue with them, and stop polluting this thread.

#72 as a non-profit extension developer (Privacy Badger by EFF) I completely support #73 and gorhill's comments on this. Your arguments are inane. There is no security risk that is exacerbated by allowing extensions to block websocket requests beyond the already existant security problems of extensions.
There are many quite legitimate reasons that adblocking and tracker blocking extensions want to intercept *all* network calls. Especially as long as your industry keeps using super cookies and fingerprinting to track users. I am sure you are well aware of this fact which is why you are here fighting so hard against this API.
Google devs, please pay attention to this issue, it is extremely important for all of us who are writing tracking protection software.

Although not directly related to the "industry versus private (single) user" debate per se, this will have repercussions in what other programmers can dictate onto a browser's visitor.
It is a creative use to use/misuse/abuse WebSockets to attempt to bypass adblocking but it still remains an invasion of privacy nonetheless. So I can only agree with comment #73 and #74 and have to wonder about Comment #72 a lot. This is not solely about adblocking per se - it also is about what is deemed "permissible" by the google chromium team for third party content providers to dictate onto visitors and what kind of control the visitor will have over content sent to their browser(s).

@72 If a for-profit organisation is what it takes to ensure that ad-networks are doing their due-diligence when it comes to protecting consumers against malicious and invasive ads, then so be it.
The ad networks put themselves in this corner with their greed. If they spent even 1% of their revenue, ensuring that the ads run on their networks were SAFE to run, then we wouldn't be in this situation today.
Additionally, arguing for granular permissions, or against WebSockets in particular is nonsense. NoScript exists. Content-Blockers exist. Firewalls and Anti-malware products exist. This has NOTHING to do with breaking JS functionality, as there are far more integral parts to JS out there that are disabled by extensions as it stands.
Personally, I think ALL parts of the request stack should be configurable via extensions. Extensions themselves ARE the permission set that you speak of already, and I see no reason to go more granular than what we already have for web-requests, etc.

FYI (in response to the commit description of a7a2ee3f307090e4f5dd8848ce498c939993b3db): CSP reports have always been mapped to the "ping" webRequest type (since internally CSP reports were flagged as ping by Blink).
CSP reports will be flagged as the (new) "csp_report" type once the patch for bug 637577 lands.

#90 I thought I just added noise to the thread and that I should wait to know which build for sure contains the fix. So I am on build 58.0.3026.3 (linux), and so far I have not been able to see websocket reported.

It seems that nobody thought about updating validation in Chrome Web Store. An upload fails right now:
The manifest defines an invalid url: ws://*/*. (PKG_MANIFEST_PARSE_ERROR)
The manifest has an invalid URL scheme: wss (PKG_MANIFEST_PARSE_ERROR)

Hi,
Am trying to intercept cookies in ResponseHeaders through webRequest.onHeadersReceived.
This works fine for reqular http(s) requests, but for the ws:// request containing the "Connection: Upgrade" and "Upgrade: WebSocket" headers, it doesn't seem to work: the webRequest.onHeadersReceived is never called, but a Set-Cookie header in the response is applied to the CookieJar of the page I'm on.
So I'm unable to intercept cookies set by the server on the response of the WebSocket upgrade request.
Am I maybe doing something wrong, is this by design or a bug?
My host permission is <all_urls> and my filter uses url's with the *:// protocol

Nevermind... whentrying to create teh case and coming up with a reproducible scenario, I figured out what i was doing wrong: I used *://mydomain.com/* as urls in the filter for my listeners.
Turns out *:// only maps on http and https, not on any other schema, including ws(s).
Adding the proper url's with ws(s):// schema's to the list of urls in my filter solved the problem