FeaturePolicy: Hangouts cannot access microphone from Gmail
Categories
(Web Compatibility :: Site Reports, defect, P1)
Tracking
(firefox-esr60 unaffected, firefox63 unaffected, firefox64+ disabled, firefox65+ disabled, firefox66- disabled, firefox67- disabled, firefox74+ wontfix, firefox75+ wontfix, firefox76+ fixed, firefox77+ fixed)
People
(Reporter: Mardak, Unassigned)
References
(Blocks 2 open bugs, Regression)
Details
(5 keywords, Whiteboard: [domsecurity-active])
Attachments
(2 files)
Updated•7 years ago
|
Comment 1•7 years ago
|
||
Reporter | ||
Comment 2•7 years ago
|
||
Comment 3•7 years ago
|
||
Reporter | ||
Comment 4•7 years ago
|
||
Comment 5•7 years ago
|
||
Comment 6•7 years ago
|
||
Reporter | ||
Comment 7•7 years ago
|
||
Updated•7 years ago
|
Updated•7 years ago
|
Comment 8•7 years ago
|
||
Comment 9•7 years ago
|
||
Still not enabled past nightly.
Comment 10•7 years ago
|
||
Andrea, are there plans to activate FeaturePolicy for 67 and not just in Nightly? If not, I'll mark this bug as disabled for 67 as well. Thanks
Comment 11•7 years ago
|
||
No plans for 67. Let's mark it as disabled. Thanks.
Updated•7 years ago
|
Comment 12•5 years ago
|
||
This bug now affects version 74. Setting dom.security.featurePolicy.enabled to false still provides a workaround.
Comment 13•5 years ago
|
||
[Tracking Requested - why for this release]: Hangouts issues via Gmail
I never use this functionality so I don't know how it's supposed to work but I can see the microphone picker is empty for me.
I'm not sure why this bug wasn't addressed before shipping.
Updated•5 years ago
|
Comment 14•5 years ago
|
||
This issue sounds serious. Baku, are you still working on this bug?
Should we set the priority as P1?
Comment 15•5 years ago
|
||
No, I'm not. But the issue was related to the default value for microphone and camera.
Probably 'self' is too restrictive.
Ethan, do you know who can take this bug? If nobody, I can.
Comment 16•5 years ago
|
||
It would be great if you can take this bug (actually, you're already the assignee, which is why I needinfo'd you). Thanks! :)
Comment 17•5 years ago
|
||
That would be great, thanks Baku! Let me know I can help.
FWIW I wasn't aware that this bug existed, it wasn't blocking the right bugs :(
Updated•5 years ago
|
Updated•5 years ago
|
Comment 18•5 years ago
|
||
Baku, do you have any updates on this bug? We're wondering if we can get the fix uplift to Beta 75?
Comment 19•5 years ago
|
||
:pascalc - did you mark this '+' for 74 to drive or ride-along for a dot release?
Comment 20•5 years ago
|
||
(In reply to Tim Spurway [:tspurway] from comment #19)
:pascalc - did you mark this '+' for 74 to drive or ride-along for a dot release?
potential ride-along
Updated•5 years ago
|
Comment 21•5 years ago
|
||
The spec-mandated default here is "self"
, which I believe is correct.
I see no evidence the hangouts iframe here in https://mail.google.com/mail/u/0/ is sandboxed. But I also don't even see any allow=
at all:
<iframe src="https://hangouts.google.com/webchat/u/0/frame?v=...&prop=gmail#epreld"
scrolling="no" class="a7A" width="262" height="198" frameborder="0"></iframe>
The (top) page domain here is mail.google.com
and the iframe is hangouts.google.com
which are different sub-domains of google.com
which means they're different domains, so for microphone to work I believe the top domain MUST delegate microphone policy to the iframe's domain using e.g. allow="microphone 'src'"
or allow="microphone https://hangouts.google.com"
(ditto camera).
Why this works in Chrome then (and Safari too) is a mystery, since they both appear to block between different sub-domains on e.g. github.io correctly. i.e. top domain must delegate using allow=
for cam/mic before it works.
Any chance other browsers have some builtin exception for *.google.com
?
In any case, I suggest reaching out to the gmail team on this.
Comment 22•5 years ago
|
||
github.io is on the public suffix list though so that's kind of different?
Comment 23•5 years ago
|
||
(In reply to Julien Cristau [:jcristau] from comment #22)
github.io is on the public suffix list though so that's kind of different?
Good question. I don't know how this affects feature policy. Anne, do I need my own domain to test this?
Comment 24•5 years ago
|
||
STRs (since it wasn't obvious):
- Open https://mail.google.com/mail/u/0/ and log in
- In the bottom left, click the 💬 hangouts symbol to reveal hangouts pane
- There, click the ➕ plus sign to search for someone to chat (e.g. your second email account)
- There, start chat to open chat iframe in the lower right corner
- There, click the 📞 handset symbol to call them by phone, to open adjacent call iframe
- There, click the ⚙️ gears symbol to see the image in comment 0.
Comment 25•5 years ago
•
|
||
Someone pointed out I may be looking at the wrong iframe, as there's signs of allow="microphone *"
in the code. Will investigate more tomorrow.
c = b.b.b('IFRAME', {
id: b.id || '',
src: c,
'class': 'talk_iframe',
style: 'border-style:none; width:100%; height:' + (a.h ? '100%' : '400px'),
frameborder: '0',
allow: 'microphone *; autoplay *; microphone'
});
Comment 26•5 years ago
|
||
No, feature policy doesn't do any site-related checks.
Updated•5 years ago
|
Comment 27•5 years ago
|
||
Looks like gmail is running different (non-working) code in Firefox compared to (working) Safari & Chrome. Paste this into web console:
[...document.getElementsByTagName("IFRAME")].filter(({src}) => src.includes("hangouts")).map(({allow, src}) => ({allow, src}))
Safari:
{"allow":"microphone *; autoplay *; microphone","src":"https://hangouts.google.com/webchat/u/0/load?client=sm&prop..."},
{"allow":"","src":"https://hangouts.google.com/webchat/u/0/frame2?v=1584912068&pvt=AMP3uWb_QRm0aqwps8YB2IQM8g-VMQY..."},
{"allow":"","src":"https://hangouts.google.com/webchat/u/0/frame2?v=1584912068&pvt=AMP3uWb_QRm0aqwps8YB2IQM8g-VMQY..."},
{"allow":"","src":"https://hangouts.google.com/webchat/u/0/frame?v=1584912068&hl=en&pvt=AMP3uWb_QRm0aqwps8YB2IQM8g..."},
{"allow":"microphone *; autoplay *; microphone","src":"https://hangouts.google.com/hangouts/_/hscv?pvt=AMP3uWb_QRm..."}
Chrome:
{"allow":"microphone *; autoplay *; microphone","src":"https://hangouts.google.com/webchat/u/0/load?client=sm&prop..."},
{"allow":"","src":"https://hangouts.google.com/webchat/u/0/frame2?v=1584912068&pvt=AMP3uWaAmNEb7PpzFmgs9p1ZRhNJ9pC..."},
{"allow":"","src":"https://hangouts.google.com/webchat/u/0/frame?v=1584912068&hl=en&pvt=AMP3uWaAmNEb7PpzFmgs9p1ZRh..."},
{"allow":"","src":"https://hangouts.google.com/webchat/u/0/frame?v=1584912068&hl=en&pvt=AMP3uWaAmNEb7PpzFmgs9p1ZRh..."},
{"allow":"microphone *; autoplay *; microphone","src":"https://hangouts.google.com/hangouts/_/hscv?pvt=AMP3uWaAmNE..."}
Firefox:
{"allow":"microphone *; autoplay *; microphone","src":"https://hangouts.google.com/webchat/u/0/load?client=sm&prop..."},
{"allow":"","src":"https://hangouts.google.com/webchat/u/0/frame2?v=1584912068&pvt=AMP3uWZpwRzcrWVTPvXzx1NGZxdbGm9..."},
{"allow":"","src":"https://hangouts.google.com/webchat/u/0/frame2?v=1584912068&pvt=AMP3uWZpwRzcrWVTPvXzx1NGZxdbGm9..."},
{"allow":"","src":"https://hangouts.google.com/webchat/u/0/frame?v=1584912068&hl=en&pvt=AMP3uWZpwRzcrWVTPvXzx1NGZx..."},
{"allow":"","src":"https://hangouts.google.com/webchat/u/0/blank"}
The first and last iframe appear to have allow lists for microphone in Safari and Chrome, but not Firefox.
Besides having no allow list, the last iframe in Fireox, https://hangouts.google.com/webchat/u/0/blank
is also different.
A chrome-js breakpoint (in createOffer & enumerateDevices) reveals it in turn contains its own embedded iframe:
> this._win.windowGlobalChild.browsingContext.embedderElement
<iframe id="xpcpeernwwJ" name="xpcpeernwwJ" allow="microphone *; autoplay *; microphone" style="visibility: hidden; top:…on: fixed; z-index: -1;" src="https://hangouts.google.…e.com%2Frobots.txt%22%7D">
> this._win.windowGlobalChild.browsingContext.embedderElement.ownerDocument
HTMLDocument https://hangouts.google.com/webchat/u/0/blank
As we can see, the innermost iframe does contain allow="microphone *; autoplay *; microphone"
but is itself inside another iframe that doesn't.
Since feature policy requires allow lists all the way up to the top document, before features are delegated down, Firefox works to spec and like every other browser here.
The reason it works in Chrome and Safari is because gmail uses different code there.
The fix is to reach out to the gmail team to fix this, presumably by either adding allow="microphone *; autoplay *; microphone"
to the blank
iframe, or better, use the same code as in Safari and Chrome if possible.
Comment 29•5 years ago
|
||
I've also investigated the issue. I have a quick update to share.
My focus is the "microphone" feature-policy. The chain of iframe is this:
A: mail.google.com/... FeaturePolicy=0x5647940605c0
-> B: hangouts.google.com/webchat/... FeaturePolicy=0x5647996b3620
-> C: hangouts.google.com/webchat/... FeaturePolicy=0x56479b4500d0
-> D: hangouts.google.com/hangouts/... FeaturePolicy=0x564794a44a70
-> E: hangouts.google.com/hangouts/... FeaturePolicy=0x56479a916ef0
top-level A
Directives: none. (we don't support feature-policy http header)
Result: microphone allowed only for mail.google.com
Iframe B
Directives: none.
Inheritage: It inherits feature denied for microphone. It doesn't have any custom feature-policy directives.
Result: microphone denied.
Iframe C
Directives: none.
Inheritage: It inherits feature denied for microphone. It doesn't have any custom feature-policy directives.
Result: microphone denied.
Iframe D
Directives: "microphone *" -> Feature allowed for all.
Inheritage: It inherits feature denied for microphone. It doesn't have any custom feature-policy directives.
Result: microphone denied.
Iframe E
Directives: none
Inheritage: It inherits feature "microphone" denied.
Result: microphone denied.
Result: the feature "microphone" is denied.
Comment 30•5 years ago
|
||
In this file, I tried to reproduce the iframe hierarchy of gmail.com. Open it in a webserver, on localhost.
I use navigator.mediaDevices.enumerateDevices()
because this is what gmail uses to check if the microphone is allowed.
Comment 31•5 years ago
|
||
Gmail team filed this as internal issue http://b/152904726
Updated•5 years ago
|
Updated•5 years ago
|
Updated•5 years ago
|
Comment 32•5 years ago
|
||
If I understand correctly this is not in the hands of the security engineering team then. Let’s move to Web Compat. Mike, assuming that this may not be highest-priority for Gmail folks can we ship an intervention for this in the meantime?
Comment 33•5 years ago
|
||
Tom, how hard do you think it would be to cook up an intervention for this?
Updated•5 years ago
|
Comment 34•5 years ago
|
||
This quick hack is working for me on baku's test-case (when run before the rest of the script):
const orig = Object.getOwnPropertyDescriptor(HTMLIFrameElement.prototype, "allow");
Object.defineProperty(HTMLIFrameElement.prototype, "allow", {
get: orig.get,
set: function(val) {
orig.set.call(this, "microphone *");
},
configurable: true,
});
But I'm not sure if the problematic Hangouts page is dynamically adding the iframes with JS just like in that test-case. baku?
Comment 35•5 years ago
|
||
If I understand correctly this code is replacing the allow attribute of all iframes with "microphone *"? That seems too insecure to ship. This would give even ad iframes the ability to listen in on your calls.
I think preferably we could poll for the iframe chain mentioned in comment 27 and add a microphone allow attribute to it only.
Thoughts? :)
Comment 36•5 years ago
|
||
I agree with Johann. Your code would work on Hangouts, allowing the use of the microphone to any iframes. Better to follow the iframe chain.
Comment 37•5 years ago
|
||
I of course agree, I just didn't know which specific domains to allow through, so I went with a general proof-of-concept :)
Since I'm not hearing "no" from baku, it seems the answer to Mike is: yes, we can use code like I suggested, we'd just want to limit it to run only on the specific iframes we want to let through. For instance we could presumably just add an if-statement to it like this (and ensure it only runs in the first place on frames from GMail/Hangouts as usual in the webcompat addon):
const orig = Object.getOwnPropertyDescriptor(HTMLIFrameElement.prototype, "allow");
Object.defineProperty(HTMLIFrameElement.prototype, "allow", {
get: orig.get,
set: function(val) {
if (document.domain == "hangouts.google.com") {
val = "microphone *";
}
orig.set.call(this, val);
},
configurable: true,
});
Comment 38•5 years ago
|
||
Thanks Tom. Let me file a separate bug for the actual intervention.
Comment 39•5 years ago
|
||
Hi Mike, is this bug then obsolete? Should we track the other one for releases as mitigation for this regression?
Comment 40•5 years ago
|
||
Since the intervention wouldn’t solve the issue just mitigate it and this bug has a lot of context I would vote for keeping it open :)
Comment 41•5 years ago
|
||
Agree with Johann, we can keep this one open (but probably not worth tracking once we ship the intervention).
Comment 42•5 years ago
|
||
The intervention should be available in 76.0b7 shipping soon.
Comment 43•5 years ago
|
||
Note that we're also in contact with Gmail folks and according to them a fix will be available soon. Let's monitor the situation and evaluate whether we need to ship the intervention. It's definitely good to have it for now.
Updated•5 years ago
|
Comment 44•5 years ago
|
||
Oana, can you verify that the next Beta fixes this issue (with the intervention applied)? You should see "GMail Hangouts microphone fix" in about:compat to know you have the right Beta. :)
Comment 45•5 years ago
|
||
Mike, with the "GMail Hangouts microphone fix" intervention enabled (and if I am fast enough to access the ⚙️ "Settings" - I don't have credit) the issue is not reproducible according to comment 24 scenario - Microphone permission is temporary allowed and Microphone field is populated.
https://prnt.sc/s4j513
https://prnt.sc/s4j25t
Disabling the intervention Microphone permission is not asked and Microphone field remains empty.
Tested with:
Browser / Version: Firefox Beta 76.0b7
Operating System: Windows 10 Pro
Comment 46•5 years ago
|
||
Calling this fixed for Fx76 via webcompat intervention.
Comment 47•5 years ago
|
||
This was fixed by Gmail today (not sure if that means FIXED or WORKSFORME). It would be great if everyone could confirm that this is fixed without the intervention applied (you can disable it in about:compat).
Thanks!
Comment 48•5 years ago
|
||
Yep, verified.
(Typically we close things as fixed if the site does something to fix it)
Updated•5 years ago
|
Updated•4 years ago
|
Updated•6 months ago
|
Description
•