flatpak / xdg-desktop-portal

Desktop integration portal
https://flatpak.github.io/xdg-desktop-portal/
GNU Lesser General Public License v2.1
547 stars 183 forks source link

Portal to open file and neighbouring files #463

Open hadess opened 4 years ago

hadess commented 4 years ago

We're missing a UI that would make it possible to opening a file, eg. a project file, and also give access to the rest of the files in that same directory. This is useful for:

UI-wise we could have:

New use cases, UI ideas, or prior art? Please list them below.

hadess commented 4 years ago

From https://github.com/flathub/flathub/pull/1415, sqlite would like to be able to write the main db, as well as some files in the same directory such as its journal.

TingPing commented 4 years ago

I wonder if its valuable to limit it to just specific files matching a pattern rather than all of a directory.

hadess commented 4 years ago

I wonder if its valuable to limit it to just specific files matching a pattern rather than all of a directory.

Maybe, for something like video players wanting to access subtitles, but that might be complicated for all other types of projects, where the name/extensions of assets wouldn't be known until the main file was parsed.

TingPing commented 4 years ago

Yeah media players is what I was thinking of, using a pattern could improve the UX, it could know no other files match and just behave as normal without constant double prompts.

matthiasclasen commented 4 years ago

Am I wrong to expect this to be just an option in the OpenFile method of the file chooser ?

hadess commented 4 years ago

Am I wrong to expect this to be just an option in the OpenFile method of the file chooser ?

The priority would be to discuss the UI and the use cases for now, not the implementation. This will tell us whether we want an option for the OpenFile method, or something else. For the media players use case discussed above an option won't be enough, as we need to return multiple files.

saivert commented 3 years ago

I feel this is going to get very complicated. At some point you just have to concede and accept a gaping hole in the sandbox for certain kinds of applications. Music and video apps that need access to companion .cue or .srt files will just need access to the same folder (and subdirs) so they can load those files. Otherwise you need various mechanisms of increasing complexity to allow the portals to figure out which files to give access to.

For fun I could think of using javascript programs that is submitted by the app via the portal API and which will parse the selected file in the file chooser and spit out a list of associated filenames. But for very complex file formats this could be a daunting task. For things like .srt and .cue it should be fairly trivial to write some javascript for that purpose. With very limited API surface in the jvm this could be made perfectly safe and it would only understand a list of filenames coming from the script and it would have to be limited to the folders that the flatpak app currently has permissions to access. Or if not javascript maybe even some DSL that is designed with functions to open, read, seek and do data conversions. Or even BPF.

My skin in the game here is that I currently maintain a flatpak manifest for DeaDBeeF music player. So mp3/cue is something I would like support for opening.

ptomato commented 3 years ago

In case more use cases are wanted: the Inform compiler takes as input a project folder "Foo.inform" (which the user can select with a file chooser in the UI) and expects to be able to create an assets folder "Foo.materials" as a sibling of "Foo.inform".

I think this would be able to be handled by a new option for the OpenFile method.

somas95 commented 3 years ago

And more use cases: currently I have to disable the sandbox in Apostrophe because otherwise I can't render a markdown document with images (which are not embedded due to the plaintext nature of markdown)

I can see the same happening for IDEs, which need access to a whole folder, or any kind of editor where data is linked instead of bundled

teohhanhui commented 3 years ago

Another media player use case in https://github.com/flathub/io.github.celluloid_player.Celluloid/issues/28

Mikenux commented 3 years ago

Hello ! It is also needed for playing external audio files (and maybe video files) linked to PDFs (software use here: GNOME Document Viewer [Evince]) in full sandboxing.

gasinvein commented 2 years ago

Apps that run win32 binaries via Wine, e.g. Bottles and protontricks, could benefit from this as well. An .exe can be opened via portal, but if it's not self-contained and require some .dlls in the same directory, it won't work.

BrainBlasted commented 2 years ago

For image viewers like EOG, we want to be able to browse images adjacent to the one the user opens.

ssokolow commented 2 years ago

Aside from GTK applications that haven't yet migrated to GtkFileChooserNative yet, this is probably the number-one reason I have huge exceptions in my sandboxing:

  1. Browsers need to read subresources when loading file:// URLs and need to write _files directories when Ctrl+S-ing.
  2. MPV needs to read subtitle files when opening video files, and needs to read video files when opening the .edl files I generate to skip ads, sponsor notices, and the odd skit that goes on too long in old Spoony videos. (Currently, I've used overrides to disable MPV's network access and grant host:ro.)
  3. Emulators need access to .bin files when they open .cue files
  4. Anything that uses SQLite for its container format, for previously stated reasons.
BrainBlasted commented 2 years ago

There's an adjacent issue - when passing a URI (for opening via the file manager or app chooser portal) apps also need a way to handle that. A solution for GtkFileChooser doesn't work for every case.

WhyNotHugo commented 2 years ago

Regarding the UX aspect of this: a clear and non-confusing API for this, is to:

Some things I kept in mind:

WhyNotHugo commented 2 years ago

When starting applications that take a file as an argument (e.g.: an image viewer when double clicking on a file in a file manager), it would also be handy to sometimes have access to the directory containing the file.

For example, if I double click on an image, I want an image viewer to render it. But I also want to easily navigate back and forth across sibling images. Having to grant the flatpak access to that whole directory ahead of time is very inconvenient.

The same applies to double clicking on videos which have separate subtitles. This scenario doesn't go via a FileChooser portal, so might be trickier.

wjt commented 2 years ago

There's an adjacent issue - when passing a URI (for opening via the file manager or app chooser portal) apps also need a way to handle that. A solution for GtkFileChooser doesn't work for every case.

Another case where I ran into this: LibreOffice has a Help extension, and tries to open it in the system browser. The browser, if it is also sandboxed, gets access to index.html but not the neighbouring files. #555

Mikenux commented 2 years ago

@hadess: Assuming the goal is to at least always read files, isn't it safe to automatically allow apps to only read files? Isn't the problem in writing files?

ssokolow commented 2 years ago

@Mikenux I assume it'd reduce the threat potential... though there would still need to be some way to allow write access for things like opening a project in an IDE (open the project definition in the root of the project and get access to the rest of the source files) or using "Web Page, Complete" when hitting Ctrl+S in a browser.

smcv commented 2 years ago

isn't it safe to automatically allow apps to only read files?

Is your proposal that the ordinary File -> Open file-chooser should always give read access to the entire directory containing the selected file?

The problem is that we can't guess what the user wants, so a UI for doing this sort of thing would need to be really clear about what is going to happen, to set up the right expectations. Otherwise, anyone whose expectations don't match the reality will be justifiably upset.

If you browse to ~/Pictures/2022/landscapes and open one photo, you might reasonably expect that an image viewer will be able to see other photos in the same directory. But, if you browse to ~/Documents and open ~/Documents/funny picture of a cat.jpg, you might be extremely upset to find that the same application (perhaps a chat app) can now read ~/Documents/banking details.pdf. The portal cannot programmatically tell the difference between your expectations in those two cases.

Mikenux commented 2 years ago

@ssokolow : Of course, there's the case for write access, but if it's possible to not ask the user to read files, that's better. I mean regular users expect to have a dialog asking them to write a file (save) more than a dialog asking them to read a file or directory (open/list).

@smcv: As I just told ssokolow, the goal is to not even prompt the user in case of "read". Regarding your example, are you talking about automatically reading files and the application sending them over the network? If so, if the chat app automatically read bank details.pdf, I wouldn't be "extremely upset" because I wouldn't notice it doing so. If I open this same file with a PDF reader, I don't know what the PDF reader can do with the file. The same goes for pictures that I don't want to "share" without consent. Also, even if you grant access through a dialog box, you are sure that the app wants to read files, but you don't know what the app will do with the files. The only advantage is like in your example: countering possibly malicious readings. So if it is the app reading user files and then sending the retrieved information to the internet, maybe in this case the apps without network permission can get the read access without consent. I'm clearly not an expert, I just think the direction to take is to know the cases better to disturb the user less with dialog boxes...

hadess commented 2 years ago

Implementing this functionality in a way where the user doesn't realise they're sharing more than the file they thought they selected is a non-starter.

@Mikenux You're right that asking less questions is good, but not asking questions at all, or asking questions that aren't understood is clearly worse.

I don't think there's any point discussing this functionality until we know how the UI should be designed. Prior art from other OSes and applications would be useful.

ssokolow commented 2 years ago

So if it is the app reading user files and then sending the retrieved information to the internet, maybe in this case the apps without network permission can get the read access without consent.

@Mikenux The application without network access might have D-Bus access to something that does have network access and can be used to perform an HTTP request for them. It's known as the confused deputy problem and it's one of the reasons defence in depth like this is necessary.

WhyNotHugo commented 2 years ago

isn't it safe to automatically allow apps to only read files?

No, other files may contain sensitive or confidential information, access should never be granted automatically.

I don't think there's any point discussing this functionality until we know how the UI should be designed.

I think it's good to continue enumerating distinct use cases so we can make sure we design in a way that catches all corner cases.

Prior art from other OSes and applications would be useful.

I don't think there is much, but IIRC, on macOS applications can prompt for permissions to access an entire directory, but only for well-known ones. There's also no granularity.


I think a good approach UX wise is to use the regular filechooser, and then show a small followup dialog asking for permission to read neighbouring files. This keeps complexity (UX wise) to a minimum, but also makes the extra access request explicit. Being a separate yes/no dialog prevents accidental confusion.

I don't think it can be less than two click when you're asking for two distinct permissions, and granting access must always be explicit (eg: a small checkbox at the bottom of a file chooser is easy to miss).

ssokolow commented 2 years ago

I think a good approach UX wise is to use the regular filechooser, and then show a small followup dialog asking for permission to read neighbouring files. This keeps complexity (UX wise) to a minimum, but also makes the extra access request explicit. Being a separate yes/no dialog prevents accidental confusion.

I don't think it can be less than two click when you're asking for two distinct permissions, and granting access must always be explicit (eg: a small checkbox at the bottom of a file chooser is easy to miss).

That'd be a distinct annoyance and incentive to continue packaging with looser manifest permissions for anything like an IDE where the typical case is going to be granting the entire folder.

I think it's important to keep brainstorming.

(Bear in mind that, from what I remember, the big hold-up for getting things like GIMP and Inkscape onto GtkFileChooserNative is whether they're willing to risk regressing the in-chooser preview pane. Maintainers can be picky about these things.)

hadess commented 2 years ago

I think a good approach UX wise is to use the regular filechooser, and then show a small followup dialog asking for permission to read neighbouring files. This keeps complexity (UX wise) to a minimum, but also makes the extra access request explicit. Being a separate yes/no dialog prevents accidental confusion.

I don't think it can be less than two click when you're asking for two distinct permissions, and granting access must always be explicit (eg: a small checkbox at the bottom of a file chooser is easy to miss).

If either having 2 dialogues, or a checkbox in a dialogue were good enough, then it would already be implemented. It isn't...

hadess commented 2 years ago

That'd be a distinct annoyance and incentive to continue packaging with looser manifest permissions for anything like an IDE where the typical case is going to be granting the entire folder.

IDEs can already use the OpenFolder portal.

ssokolow commented 2 years ago

IDEs can already use the OpenFolder portal.

  1. I just gave IDEs as an example.
  2. Not all IDEs and IDE-like things use "Folder containing a Well Known filename" as their structure. Some have a project file with an arbitrary name such that you could have multiple projects sharing a single folder.
WhyNotHugo commented 2 years ago

We could have a new permission for Flatpaks that elevantes all "open file" calls to "open file and neighbouring files".

So something like an IDE can [at install time] request this permission, and then any time a file is opened, so it the directory.

This gives really good usability for this kind is scenario, but makes it impossible to open a file without sharing the entire directory.

I do believe there are scenarios where this approach is the one that makes sense the most, but for other type of applications, the second pop up is still best. In reality, the new permission would skip the dialog on the second call and always grant the followup request.

swick commented 2 years ago

Not all IDEs and IDE-like things use "Folder containing a Well Known filename" as their structure. Some have a project file with an arbitrary name such that you could have multiple projects sharing a single folder.

You have to explain why the OpenFile with the directory option doesn't work in that case because I don't get it.

swick commented 2 years ago

There seems to be three relatively unrelated use cases

  1. apps which have workspaces
  2. files which depend on other files
  3. apps which can be used to browse a certain file type in a folder

The first one is for example IDEs, video editors, etc. They can use the OpenFolder portal to add workspace directories.

The second one is really tricky. Maybe we could have some heuristics in the portal which checks the file type/mime type and filename to figure out if the whole folder might be required. In that case the user can be told that the entire directory might be required and let the user pick between "entire directory" or "only this file" with default to "entire directory".

The third one might actually be a good candidate for a static permission listing the mime types of objects it wants to be able to browse. Not sure about it at all though.

ssokolow commented 2 years ago

You have to explain why the OpenFile with the directory option doesn't work in that case because I don't get it.

Because the application wants you to select some form of ArbitraryName.project file, rather than the folder it resides within, but then needs to access its siblings within the folder. (Similar to Foo.html and Foo_files with saved web pages.)

swick commented 2 years ago

Because the application wants you to select some form of ArbitraryName.project file, rather than the folder it resides within, but then needs to access its siblings within the folder. (Similar to Foo.html and Foo_files with saved web pages.)

That's just a broken app then which doesn't use the directory option when it should?

e: if the app really only wants to open folder with the filename "ArbitraryName.project" in it maybe we can add an directory_requires_filename option to the OpenFile portal.

ssokolow commented 2 years ago

That's just a broken app then which doesn't use the directory option when it should?

No, it's an app that wants a file, which depends on other files. Would you say a web browser is a "broken app" for not using a directory picker and then implementing its own file picker to choose between the HTML files within the picked directory?

ssokolow commented 2 years ago

e: if the app really only wants to open folder with the filename "ArbitraryName.project" in it maybe we can add an directory_requires_filename option to the OpenFile portal.

If, by that, you mean that it displays a file picker, mounts the containing folder into the documents portal as if it were selected in a directory picker, and then returns the document portal path to the picked file, that would certainly work.

The part that complicates things is that whole "Application needs access to the folder, but can't derive the file's name from it because there may be more than one".

Mikenux commented 2 years ago

@ssokolow :

@Mikenux The application without network access might have D-Bus access to something that does have network access and can be used to perform an HTTP request for them. It's known as the confused deputy problem and it's one of the reasons defence in depth like this is necessary.

If an application has access to something that has network access, I believe the application is not fully sandboxed. If an application has this type of permission, even if you ask the user to read a file/directory (so several files), it does not prevent this application from sending these files afterwards. The only protection is possibly when the application wants to read a file while the user is not aware of it (in the case where the application can only read one file at a time). Am I right?

saivert commented 2 years ago

There are requests for prior art but there is none. Other platforms just request blanket permission for single applications to your documents, pictures, downloads.

Flatpak has for reasons specifically opted to not go this route and instead let each app just specify sandbox exceptions in the metadata that the user needs to use third party software to control (FlatSeal). The only area where it seems to be some proper permission granting dialog boxes is for things like camera and screen sharing access.

Now work has completed on the feature that allows applications to resume camera and screen sharing sessions.

The design you go for will have consequences.

swick commented 2 years ago

@ssokolow I misunderstood what you were saying and it indeed looks like it's a 4th use-case. The only way I see how this could be implemented is if the folder name is derivable from the filename, otherwise you just have to give up and open the containing folder.

ssokolow commented 2 years ago

@Mikenux Like most security situations, the confused deputy problem often comes up in situations where something isn't supposed to have access, but does by mistake.

That's why it's so important to have defense in depth... so if a flaw is found in the sandboxing for network access (eg. a detour through a D-Bus service that people writing the sandbox manifest didn't realize could be used to send network requests), the program still doesn't automatically have access to the potentially sensitive files.

(Look at how the log4j JNDI vulnerability happened, for example.)

Mikenux commented 2 years ago

@ssokolow : Yes. However, the ideal sanboxed application has access to nothing: no network access, no d-bus access to communicate with/to another application, no write access.

Regarding the portal, I mean that even if you ask users to grant access to files, users certainly do not know what the application will do with them. And as I said, users can use applications to open sensitive files (for example, the PDF viewer example I gave). So even if you have a portal between your files and an application (even to only open a single file, and especially a sensitive file), but that application has network access (via direct network access or a d-bus service) to do malicious things, it won't change anything. Continuing with the PDF viewer example, if the app is marked as insecure/potentially unsafe, but has functionality for sharing files over the internet, a user will definitely use it - and it is a malicious app. More than that, if this PDF viewer has the ability to open multiple files at once, the user will definitely grant it permission to do so. Finally, unless I'm completely wrong in this comment, you'll need more protection (more defense in depth) than just asking the user.

ptomato commented 2 years ago

Could we keep the discussion on topic to use cases for this feature, ideas for UI design, and prior art? Debating the fundamental nature of sandboxing is interesting but makes it a bit difficult to follow for people like me who are trying to follow news of the feature :smile:

WhyNotHugo commented 2 years ago

It seems that we have basically three scenarios:

  1. A user picks a file (via file chooser) and the application always needs access to neighbouring files (the IDE opening a "project file" example given above. Is this the only use case?).
  2. A user picks a file (via file chooser) and the application sometimes needs access to neighbouring files (Firefox opening an HTML file via File>Open)
  3. A user launches an application passing a file as argument, and always needs access to neighbouring files.
  4. A user launches an application passing a file as argument, and sometimes needs access to neighbouring files (e.g.: double clicking on a playlist file or HTML file on a file manager)

I believe that (1) and (3) can be handled with an extra flatpak permission that needs to be granted. (2) and (4) are best addressed with the follow-up prompt.

teohhanhui commented 2 years ago

Are (1) and (2) really different? The app probably can't tell ahead of time which sibling/child directories/files are needed. So shouldn't the user's choice be whether to allow access to the directory the file is contained in or not?

Seeing a prompt for (4) seems jarring. If a user opens a playlist file, they always want to allow access to the actual media files, no?

somas95 commented 2 years ago

There is another issue to keep in mind. Are we allowing recursive file access? Some of those scenarios would require it (i.e, IDE folder structures usually work with subdirectories, resources for html/markdown files, etc). The obvious issue is that if recursive directory access is granted opening a file in HOME means having access to all files of the user. Maybe would be interesting to somewhere explicit what files are being accessed by the app, just as there are indicators for when the screencapture portal is being used, at least in GNOME


From: Teoh Han Hui @.> Sent: Saturday, February 26, 2022 3:20:45 PM To: flatpak/xdg-desktop-portal @.> Cc: somas95 @.>; Comment @.> Subject: Re: [flatpak/xdg-desktop-portal] Portal to open file and neighbouring files (#463)

Are (1) and (2) really different? The app probably can't tell ahead of time which sibling/child directories/files are needed. So shouldn't the user's choice be whether to allow access to the directory the file is contained in or not?

— Reply to this email directly, view it on GitHubhttps://github.com/flatpak/xdg-desktop-portal/issues/463#issuecomment-1052140319, or unsubscribehttps://github.com/notifications/unsubscribe-auth/ACEAIN7EROBYUIVBOPCVJXLU5DOT3ANCNFSM4LUL5H2Q. Triage notifications on the go with GitHub Mobile for iOShttps://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Androidhttps://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub. You are receiving this because you commented.Message ID: @.***>

ssokolow commented 2 years ago

Recursive access is so common that I actually had to think for a moment to come up with situations where you wouldn't need it. (With the browser-produced _files sidecar folder probably being the most common example)

The situations I came up with which probably don't need it are:

...so, basically, formats that use a sidecar file to add metadata to something without altering its format, similar to Apple's AppleDouble format for storing resource forks and data forks side-by-side on non-HFS filesystems.

The more typical case is things such as any document format that links resources rather than embedding them, which has a 50/50 chance of keeping subresources in a sibling folder to organize them. (HTML, LyX documents and the LaTeX they render to, Inkscape SVG if you choose the Link radio button when importing an external image, etc.)

In fact, those could sort of be considered examples of "project workspaces which don't impose a specific Well Known Filename", since, from what I remember, LyX allows you to do things like having one .lyx file per chapter with some subresources shared between multiple chapters, and a top-level .lyx file which combines them into a single manuscript.

WhyNotHugo commented 2 years ago

Are (1) and (2) really different? The app probably can't tell ahead of time which sibling/child directories/files are needed. So shouldn't the user's choice be whether to allow access to the directory the file is contained in or not?

The difference is whether the application sometimes requires extra access, or always.

An application that opens "project files" will always need access to sibling files, so it's reasonable to grant the extra permission once at installation time.

A browser opening an HTML file only sometimes needs extra access, so it's logical to only ask in those specific scenarios. Especially since opening ~/cat-meme.png in Firefox shouldn't grant it access to my entire home right away.

Seeing a prompt for (4) seems jarring. If a user opens a playlist file, they always want to allow access to the actual media files, no?

I agree on the sentiment, but you can't know that the file is playlist before opening it. Not unless the portal itself is capable of recognising filetypes -- but that sounds like a pretty big rabbit hole.


@ssokolow thanks for additional good examples!

ssokolow commented 2 years ago

A browser opening an HTML file only sometimes needs extra access, so it's logical to only ask in those specific scenarios. Especially since opening ~/cat-meme.png in Firefox shouldn't grant it access to my entire home right away.

Maybe files directly in the home directory should be special-cased, similar to how Flatpak blacklists various paths like /boot, /root, and /var when you specify filesystem=host.

ptomato commented 2 years ago

Are (1) and (2) really different? The app probably can't tell ahead of time which sibling/child directories/files are needed.

I think that depends on the app? I think it'd be reasonable for, say, a media player to ask ahead of time for access to a sibling subtitle file with same name as the video file being opened, but with the extension replaced by .srt, if such a file exists. Or in my use case, the Inform IDE, when the user opens Foo.inform, to ask ahead of time for permission to access a sibling folder Foo Materials and also permission to create it if it doesn't exist.

ssokolow commented 2 years ago

I think it'd be reasonable for, say, a media player to ask ahead of time for access to a sibling subtitle file with same name as the video file being opened, but with the extension replaced by .srt, if such a file exists.

Media players are an interesting case, because they straddle the line. Sometimes needing to access sibling files with predictable names (eg. subtitles) and sometimes needing paths that can only be derived after the file has been opened (eg. .pls, .m3u, XSPF, EDL, etc.).

Also, SubRip (.srt) isn't the only subtitle format. for example, there's SubStation Alpha (.ssa) and its advanced variant (.ass) as well as the more interesting case of the subtitle files you'll get out of something like youtube-dl.

The Netherlands welcomes Trump in his own words-j-xxis7hDOE.mp4
The Netherlands welcomes Trump in his own words-j-xxis7hDOE.en.vtt

...and yes, MPV will automatically find the latter filename if given the former.

Another interesting case I can present, which I use a lot, is MPlayer/MPV Edit Decision Lists, which are basically playlist files that let to specify parts of files.

For example, I have a PySceneDetect-based script which wraps youtube-dl and produces EDLs, because The Young Turks is so bad about rapidly cutting into an irritating, carnival barker-esque "Wanna pay us to get even more content?" post-roll ad after each clip.

(Seriously. Sometimes, they cut so close that the last word in the actual content gets cut off.)

Activision-Blizzard Pushes COMICAL Anti-Union Propaganda [60QSENi88o0].mp4.mpv.edl
Activision-Blizzard Pushes COMICAL Anti-Union Propaganda [60QSENi88o0].mp4

Note that the file names are purely my own choice. The actual connection is made by the contents of the EDL file looking like this:

# mpv EDL v0
%74%Activision-Blizzard Pushes COMICAL Anti-Union Propaganda [60QSENi88o0].mp4,0,421.6212