[MediaControl-Linux] Show artwork image on the virtual control interface (MPRIS)
Categories
(Core :: Audio/Video: Playback, task, P1)
Tracking
()
Tracking | Status | |
---|---|---|
firefox81 | --- | fixed |
People
(Reporter: chunmin, Assigned: chunmin)
References
Details
Attachments
(7 files)
47 bytes,
text/x-phabricator-request
|
Details | Review | |
147.49 KB,
image/png
|
Details | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review |
Show the MediaImage defined in media-session to the MPRIS interface.
Per bug 1623971 comment 12, we could use data url to work around the security issue.
I'd be interested in maybe working on this over a few weekends if someone tells me where to start, or maybe after the Windows infrastructure lands so I can see how it looks from there.
Assignee | ||
Updated•9 months ago
|
Assignee | ||
Comment 2•9 months ago
|
||
(In reply to Ilya K from comment #1)
I plan to sort some common things out in Windows part first and then bring them to Linux part.
- For security reason, Firefox shouldn't throw some random URL to the underlying API directly, so the plan is to fetch the image inside Firefox and then check if it's valid
- We need some cache mechanism to avoid fetching the same image repeatedly
Assignee | ||
Comment 3•9 months ago
|
||
I tried using data url on Ubuntu this morning but it doesn't work.
The image is from http://rust-lang.org/logos/rust-logo-16x16.png
and it's converted data uri from is: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABOUlEQVR4AYTMAecUQRjH8QfAvYR9C3WXpCtpk6TdPYlWOoSIO0S5UpLewIDRu1jsCwh0kAEQCEBBADQYAL++fx7+Z1n35WPGM4+xaV+aKzUCErJLCKhtrs/N1QoRBZpREFHZaZ+aZYUBckfsIfQQvkFuwOUnH5prEcJvvMfC54L8vvC3vxCiGb1rr9co0Bmj7+8gFNT2tr0RIPTQGTuMkAv2ur2ZoCn8wUeXIYwQegjJ9u2tDGFpxCn3D0d8h9wPjJDL9qq7kyGsjPw+57nvLCFke9ndTRDeGHHK/cQaW8j9muwke9HdCxAyNIX13BuCbbv7NQo04za+QhMFtRk96x5ECD2EhU26mE12opn3dPOwwgC5Iw5YuYPP5AZUdtqTzaMKEQWaURBR2VyPN02NgITsEgL+DyM7AwBIx19/QAPbbQAAAABJRU5ErkJggg==
The data uri is converted from
Assignee | ||
Comment 4•9 months ago
•
|
||
I worked out a prototype, by creating a temp image file (via nsIFile
) and feed it to MPRIS. The patch is quite ugly now though.
I found that "mpris:artUrl"
has some kind of cache mechanism, at least on Ubuntu 18.04:
- The image shown on the notification bar won't be updated as long as the URL of the image is the same, even if the whole image file is overwritten/updated
- Once the image URL is used, its image is cached. Even the original image is destroyed
- For example,
- Open Firefox with a media element. The MPRIS would start automatically.
- Feed image A whose filename is
test-1.png
to"mpris:artUrl"
, the MPRIS image will be image A - Feed image B whose filename is
test-2.png
to"mpris:artUrl"
, the MPRIS image will be image B - Close Firefox
- Open Firefox with a media element again. The MPRIS would start automatically.
- Feed image C whose filename is
test-1.png
to"mpris:artUrl"
, the MPRIS image will be image A- What a surprise! I guess it's image C, but it's not!
- Therefore, it's better to create a unique image URL for each image. Now I use a timestamp as a unique identifier.
- For example,
Assignee | ||
Comment 5•9 months ago
|
||
Sorry for the slow response, but data: URIs definitely do work for me on Plasma. Other implementations might not support them, though.
Assignee | ||
Comment 7•8 months ago
•
|
||
Tim,
Due to the limitation of the MPRIS in the gnome-desktop environment (e.g., ubuntu), the implementation needs to download the image specified by an URL to a local file. Since the local image file could be read by other applications if it has permission. For privacy, this process runs only when tracking-protection is disabled but I am not sure if it's enough. I was wondering if you could share your opinions. Or do you know who is the right person I should ask?
Comment 8•8 months ago
|
||
I think it's fine in terms of privacy because the image is located in a local file. So, there is no network request made. And we don't really block requests to the local resource for tracking-protection. The only privacy threat I can think of is that third-party software might be able to inspect image files to know information about users, maybe about their tastes about music. But, I think it's a low privacy risk if we don't write users' data into the image file. That is my two cents.
Steve, could you share your insight about this? Thanks.
Updated•8 months ago
|
Assignee | ||
Comment 9•8 months ago
|
||
Depends on D80303
Comment 10•8 months ago
|
||
(In reply to C.M.Chang[:chunmin] from comment #7)
Due to the limitation of the MPRIS in the gnome-desktop environment (e.g., ubuntu), the implementation needs to download the image specified by an URL to a local file. Since the local image file could be read by other applications if it has permission. For privacy, this process runs only when tracking-protection is disabled but I am not sure if it's enough. I was wondering if you could share your opinions. Or do you know who is the right person I should ask?
Would you mind to share some additional context here:
- When the image is downloaded, does that request contain credentials (e.g., cookies)? Do you know the loadingPrincipal for this request (i.e., is it loading from system privileged code or within content)?
- What do you mean by "For privacy, this process runs only when tracking-protection is disabled but I am not sure if it's enough."?
Since the local image file could be read by other applications if it has permission.
This isn't my area of expertise, but I suspect this is true with any files we store on disk. Another application could also just read our history database.
We'd only have a concern here if web content could somehow probe to determine whether this image has already been downloaded. Is it possible for arbitrary web content to load the local file?
Assignee | ||
Comment 11•8 months ago
|
||
(In reply to Steven Englehardt [:englehardt] from comment #10)
- When the image is downloaded, does that request contain credentials (e.g., cookies)? Do you know the loadingPrincipal for this request (i.e., is it loading from system privileged code or within content)?
The image would only be downloaded within the chrome process. The URL is loaded via asyncOpen
in nsIChannel
. It would do some security check about the passed URL.
- What do you mean by "For privacy, this process runs only when tracking-protection is disabled but I am not sure if it's enough."?
- The image would only be downloaded only when
"privacy.trackingprotection.enabled"
isfalse
- If the image is download, the permission of the download image file on Linux would be set to
644
. Permission644
on Linux means:- The file is readable and writeable by the owner of the file
- The file is readable by users in the group owner of that file
- The file is readable by everyone else
The download image might give a hint about what music or video the user is listening to or watching, so that's why the (1) above is checked for now.
I wonder
- Is it necessary to check
"privacy.trackingprotection.enabled"
before downloading an image? I am not sure if it meets what"privacy.trackingprotection.enabled"
was designed to do. - Are other preferences needed to be applied?
- Should the file-permission need to be changed to
600
(only readable and writeable by the owner of the file) or other?
Since the local image file could be read by other applications if it has permission.
This isn't my area of expertise, but I suspect this is true with any files we store on disk. Another application could also just read our history database.
I saw the file permission of cookies.sqlite
is 644
as well, at least in Firefox Nightly.
We'd only have a concern here if web content could somehow probe to determine whether this image has already been downloaded. Is it possible for arbitrary web content to load the local file?
I don't find a Browser Extensions API that allows a browser extension to read local files. So it should be fine.
However, the add-on developer can use XPCOM nsIFile interface in the past. So if users install an unauthenticated add-on that calls nsIFile
. That add-on might have a way to read the downloaded image.
Assignee | ||
Updated•8 months ago
|
Comment 12•8 months ago
|
||
We would definitely want to ensure the image is downloaded credential-less and using the Null principal. Christoph can review/guide you on how to make sure that is the case. We would want to restrict the schemes allowed, it should only be http/https - no about: or file:// or otherwise.
I am not thrilled about it being downloaded in the chrome process; but I'm not sure a reasonable alternative exists.
I do not feel like checking privacy.trackingprotection.enabled
is necessary; but I don't know under what circumstances this code is being hit. If we're already sending media data over this interface I feel like web tracking is not really coming into play here?
This entire feature should be behind a pref 'just in case'.
I don't know if we have a standard for what permission bits we set on what are essentially temp files created on Linux. Hopefully this is an easy question for gcp?
Comment 13•8 months ago
|
||
(In reply to C.M.Chang[:chunmin] from comment #11)
(In reply to Steven Englehardt [:englehardt] from comment #10)
- When the image is downloaded, does that request contain credentials (e.g., cookies)? Do you know the loadingPrincipal for this request (i.e., is it loading from system privileged code or within content)?
The image would only be downloaded within the chrome process. The URL is loaded via
asyncOpen
innsIChannel
. It would do some security check about the passed URL.
Thanks. Tom has already flagged the right folks that can give advice from here.
- What do you mean by "For privacy, this process runs only when tracking-protection is disabled but I am not sure if it's enough."?
- The image would only be downloaded only when
"privacy.trackingprotection.enabled"
isfalse
- If the image is download, the permission of the download image file on Linux would be set to
644
. Permission644
on Linux means:
- The file is readable and writeable by the owner of the file
- The file is readable by users in the group owner of that file
- The file is readable by everyone else
The download image might give a hint about what music or video the user is listening to or watching, so that's why the (1) above is checked for now.
I wonder
- Is it necessary to check
"privacy.trackingprotection.enabled"
before downloading an image? I am not sure if it meets what"privacy.trackingprotection.enabled"
was designed to do.- Are other preferences needed to be applied?
- Should the file-permission need to be changed to
600
(only readable and writeable by the owner of the file) or other?
From a web tracking perspective my only concern is whether a remote party could use the image requests to learn about your listening history and tie that to your web browsing. How does the browser know the URL to fetch the image? Who would ultimately provide that URL?
Checking privacy.trackingprotection.enabled
is not the right approach, as you suspected. This pref is set to true when the user has ETP Strict enabled -- it basically signifies whether or not the feature is enabled.
A good first step here would be to ensure the request is not credentialed. You can do that by adding the LOAD_ANONYMOUS
flag to the channel. This will strip cookies and HTTP Auth credentials from the request.
Since this load is from chrome it's unclear to me if the URL classifier will run against the request. Assuming it's an arbitrary URL specified by a remote party, it seems prudent to also run the channel through the URL classifier and block requests to known tracking domains (e.g., if the album image was loaded from "doubleclick.net" for some reason). Dimi should know whether the request will be classified, and if there's a way to force classification.
Since the local image file could be read by other applications if it has permission.
This isn't my area of expertise, but I suspect this is true with any files we store on disk. Another application could also just read our history database.
I saw the file permission of
cookies.sqlite
is644
as well, at least in Firefox Nightly.We'd only have a concern here if web content could somehow probe to determine whether this image has already been downloaded. Is it possible for arbitrary web content to load the local file?
I don't find a Browser Extensions API that allows a browser extension to read local files. So it should be fine.
However, the add-on developer can use XPCOM nsIFile interface in the past. So if users install an unauthenticated add-on that calls
nsIFile
. That add-on might have a way to read the downloaded image.
Thanks! I was mainly concerned with whether the images were ultimately web-accessible. I.e., such that an unrelated web page could probe a set of URLs to determine whether a user has listened to a certain album. (This is similar to webpages probing web-accessible resources from extensions to determine which extensions are installed -- e.g., https://dl.acm.org/doi/abs/10.1145/3029806.3029820?download=true). It sounds like that's not a concern here.
Assignee | ||
Comment 14•8 months ago
•
|
||
(In reply to Tom Ritter [:tjr] (ni for response to sec-[approval|rating|advisories|cve]) from comment #12)
We would definitely want to ensure the image is downloaded credential-less and using the Null principal. Christoph can review/guide you on how to make sure that is the case. We would want to restrict the schemes allowed, it should only be http/https - no about: or file:// or otherwise.
The current implementation skips the URL starts with file://
. It's easy to add a check to skip about:
as well. The passed URL will be loaded via asyncOpen
in nsIChannel
. For http
or https
case, nsHttpChannel::AsyncOpen
will be called. It seems some content security check is done there.
If we're already sending media data over this interface I feel like web tracking is not really coming into play here?
Currently (without adding the patches here), the information sent over MPRIS includes track title, track artist, and album name, without checking the privacy.trackingprotection.enabled
.
What the patches here do is to pack a path to a local image file to the information sent over the MPRIS as well, besides the track info above. So maybe we can skip checking privacy.trackingprotection.enabled
and focus on what permission we should set for a temp file created on Linux?
This entire feature should be behind a pref 'just in case'.
For now, this feature is behind dom.media.mediasession.enabled
, which is only enabled in Firefox Nightly.
Comment 15•8 months ago
•
|
||
I don't know if we have a standard for what permission bits we set on what are essentially temp files created on Linux.
From a quick scan through this bug, it looks like the hostile application would potentially be running as the same user? So then it doesn't really matter? If the attacker is potentially another user, it may.
So the question is what API is used to create this "temp file". But looking at the code, it's just doing:
rv = mLocalImageFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
So it's gonna be world readable.
Assignee | ||
Comment 16•8 months ago
|
||
(In reply to Gian-Carlo Pascutto [:gcp] from comment #15)
So the question is what API is used to create this "temp file". But looking at the code, it's just doing:
rv = mLocalImageFile->Create(nsIFile::NORMAL_FILE_TYPE, 0644);
So it's gonna be world readable.
Does gecko have Web API or Browser Extension API that allows a third-party application to read the local files? If not, does changing 0644
to 0600
make it a bit safer?
Assignee | ||
Comment 17•8 months ago
•
|
||
If we have a way to check the image specified by the URL is secure, then we don't need to download the image. We can forward the URL that has been checked to the MPRIS interface directly.
The passed URL will be loaded via
asyncOpen
innsIChannel
. Forhttp
orhttps
case,nsHttpChannel::AsyncOpen
will be called. It seems some content security check is done there.
Now the security-check is done by nsContentSecurityManager
in nsHttpChannel::AsyncOpen
, via FetchImageHelper::FetchImage()
. Assume that check does the right job. As a result, if the image could be fetched successfully, then we can assume the URL specifying the image is secure. Then the URL could be forwarded to MPRIS directly, instead of saving a local copy from the fetched image and forwarding its path. Is this approach better?
Comment 18•8 months ago
|
||
(In reply to Steven Englehardt [:englehardt] from comment #13)
Since this load is from chrome it's unclear to me if the URL classifier will run against the request. Assuming it's an arbitrary URL specified by a remote party, it seems prudent to also run the channel through the URL classifier and block requests to known tracking domains (e.g., if the album image was loaded from "doubleclick.net" for some reason). Dimi should know whether the request will be classified, and if there's a way to force classification.
Right now we don't have a specific flag to force classification, but if the channel is not created by System Principal, URL classifier should classify it.
From Comment 17, it seems the image is fetched by FetchImageHelper::FetchImage()
, which uses null principal if I understand correctly, so the channel should be classified.
Comment 19•8 months ago
|
||
(In reply to C.M.Chang[:chunmin] from comment #14)
The current implementation skips the URL starts with
file://
. It's easy to add a check to skipabout:
as well. The passed URL will be loaded viaasyncOpen
innsIChannel
. Forhttp
orhttps
case,nsHttpChannel::AsyncOpen
will be called. It seems some content security check is done there.
The more we can restrict, the better obviously. So if we know that the file is only http(s), then why not flip the model around and only allow that? allow-list VS deny-list. Using FetchImageHelper::FetchImage() uses a NullPrincipal and hence can be used for the job, though I suggest we add the LOAD_ANONYMOUS flag as well so to not send any cookies. Other than that, I think we are good!
Comment 20•8 months ago
•
|
||
Does gecko have Web API or Browser Extension API that allows a third-party application to read the local files?
Extensions are allowed to communicate with native apps, which could read those files.
If not, does changing 0644 to 0600 make it a bit safer?
As already explained, this makes no difference whatsoever because it would be running as the same user anyway. If the file contains highly sensitive content, perhaps it should sit somewhere where content processes don't have access to it (i.e. where it would be blocked by sandbox restrictions)? I don't know if the current dir that is used qualifies.
I can't really give meaningful input here without understanding what the threat model would be. I can only observe what is technically possible and what is being done right now, and I'm not sure if that's really helpful :)
Assignee | ||
Comment 21•8 months ago
|
||
(In reply to Gian-Carlo Pascutto [:gcp] from comment #20)
As already explained, this makes no difference whatsoever because it would be running as the same user anyway. If the file contains highly sensitive content, perhaps it should sit somewhere where content processes don't have access to it (i.e. where it would be blocked by sandbox restrictions)? I don't know if the current dir that is used qualifies.
The permission of cookies.sqlite
on my linux is -rw-r--r--
(0644
). Is it something that should be taken care of? (open another bug maybe)
Assignee | ||
Comment 22•8 months ago
|
||
The URL specifying the track image is only valid if its scheme is http
or https.
Depends on D82806
Assignee | ||
Comment 23•8 months ago
|
||
The URL specifying the track image should be loaded without any
user-specific data like cookie headers, or HTTP Auth credentials.
Depends on D83694
Updated•8 months ago
|
Updated•8 months ago
|
Assignee | ||
Comment 24•8 months ago
•
|
||
Hi,
I wonder if saving a temporary file is a big concern (comment #20) to stop shipping the code. I am not sure what's the protocol when having a privacy concern. Is this risk acceptable if the current code is shipped? Do we have a procedure to decide whether the risk is acceptable or not?
If leaking the data through a browser extension that communicates with the third-party native app on the computer is a real concern, are all the data stored in the computer with 0644
permission (e.g., cookies, session-storage, ...) vulnerabilities?
Aside from that, the media session's information would be exposed to the D-bus interface, so any application or script reading data from D-bus can get the track info sent from Firefox, such as track title, album name, artist name, which should give more information than a temporary image. If browser extension has a way to communicate with the native app that reads data from D-bus, then all the track info could be exposed to a browser extension. Is that something we need to concern?
Comment 25•8 months ago
•
|
||
The permission of cookies.sqlite on my linux is -rw-r--r-- (0644). Is it something that should be taken care of?
That's a valid point. I don't see why we should have any files in the user profile that are world readable.
(And presumably, the fact that we're doing that immediately renders all local-other-user considerations moot until that would be fixed)
Comment 26•7 months ago
|
||
(And presumably, the fact that we're doing that immediately renders all local-other-user considerations moot until that would be fixed)
We do remove world/group-execute permissions on the profile dir which means the file still isn't readable. But there's still an issue here with best practices. dveditz has pointed out we fixed this at some point, but behavior has regressed since. Checking an old profile seems to confirm that older files in the profile were indeed only user readable.
Assignee | ||
Comment 27•7 months ago
|
||
(In reply to Gian-Carlo Pascutto [:gcp] from comment #26)
We do remove world/group-execute permissions on the profile dir which means the file still isn't readable.
So, is it ok to save a file temporarily with 0644
permission under a dir without world/group-execute permissions? It follows the same manner.
Comment 28•7 months ago
•
|
||
So, is it ok to save a file temporarily with 0644 permission under a dir without world/group-execute permissions? It follows the same manner.
I would say yes but why not use 0600
to begin with? We want to fix this for the profile.
Assignee | ||
Comment 29•7 months ago
|
||
Assignee | ||
Comment 30•7 months ago
|
||
The temporary files should be saved under a dictionary without
world/group-execute permissions
Depends on D85075
Comment 31•7 months ago
|
||
(In reply to C.M.Chang[:chunmin] from comment #24)
I wonder if saving a temporary file is a big concern (comment #20) to stop shipping the code. I am not sure what's the protocol when having a privacy concern. Is this risk acceptable if the current code is shipped? Do we have a procedure to decide whether the risk is acceptable or not?
Let's loop in Tom here. Tom is there an official procedure to follow? If not, what's your take, acceptable or not?
Assignee | ||
Comment 32•7 months ago
|
||
Comment 33•7 months ago
|
||
I wonder if saving a temporary file is a big concern
I think that's okay. My inclination about threat model is that exposing this image to a local attacker (including a compromised content process from another origin) is not a strong concern. We shouldn't do it if it's easily avoidable (and it appears we are easily avoiding doing so) but we don't need to scorch the earth ensuring we're not. We should; however, be really certain that the HTTP/HTTPS request we are making for this image is not sending any credentials (cookies, Basic Auth) nor can the response be interpreted incorrectly[0]. I'm punting that part of the assurance back to you Christoph =)
:chunmin - thanks for putting up with us through all of this. Our response is a little disorganized, in the future this type of thing would probably be best handled by emailing secreview@ in the beginning.
[0] I'm imagining something like "The image request redirects to an HTML page which is then loaded in the parent process" or "The image request redirects to facebook, and we write the HTML contents of your facebook page to the temporary file".
Assignee | ||
Comment 34•7 months ago
|
||
(In reply to Tom Ritter [:tjr] (OOTO until Aug 3) from comment #33)
We should; however, be really certain that the HTTP/HTTPS request we are making for this image is not sending any credentials (cookies, Basic Auth) nor can the response be interpreted incorrectly[0]. I'm punting that part of the assurance back to you Christoph =)
The image will only be downloaded from a HTTP/HTTPS URL (D83694) with LOAD_ANONYMOUS
flag (D83695), so the cookies and HTTP Auth credentials would be stripped.
:chunmin - thanks for putting up with us through all of this. Our response is a little disorganized, in the future this type of thing would probably be best handled by emailing secreview@ in the beginning.
Thanks for the info! I'll definitely start with an email next time.
Assignee | ||
Comment 35•7 months ago
|
||
(In reply to Tom Ritter [:tjr] (OOTO until Aug 3) from comment #33)
I'm punting that part of the assurance back to you Christoph =)
Christoph, are you ok with the current approach? I'd like to land the patches if it's ok for you.
Comment 36•7 months ago
|
||
(In reply to Tom Ritter [:tjr] (OOTO until Aug 3) from comment #33)
We should; however, be really certain that the HTTP/HTTPS request we are making for this image is not sending any credentials (cookies, Basic Auth) nor can the response be interpreted incorrectly[0]. I'm punting that part of the assurance back to you Christoph =)
Yeah, we took good care of not sending any credentials. I think we are good here - I am fine with the approach!
Comment 37•7 months ago
|
||
Pushed by cchang@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/cda926214110 P1: Set track image to MPRIS r=alwu https://hg.mozilla.org/integration/autoland/rev/a28932a71510 P2: Move same utils in SMTC and MPRIS backend to MediaControlUtils.h r=alwu https://hg.mozilla.org/integration/autoland/rev/af0e28f70bde P3: Only fetch image from http(s) URL r=ckerschb https://hg.mozilla.org/integration/autoland/rev/a40700a5fec1 P4: Load URL without user-specific data r=ckerschb https://hg.mozilla.org/integration/autoland/rev/467aa64be962 P5: Set the permission of the temporary file to 600 r=gcp https://hg.mozilla.org/integration/autoland/rev/11689ad9792d P6: Save images in a dictionary r=gcp
![]() |
||
Comment 38•7 months ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/cda926214110
https://hg.mozilla.org/mozilla-central/rev/a28932a71510
https://hg.mozilla.org/mozilla-central/rev/af0e28f70bde
https://hg.mozilla.org/mozilla-central/rev/a40700a5fec1
https://hg.mozilla.org/mozilla-central/rev/467aa64be962
https://hg.mozilla.org/mozilla-central/rev/11689ad9792d
Assignee | ||
Updated•7 months ago
|
Description
•