Writable file API


#1

Writable files

https://github.com/drufball/writable-files/ explores solutions to this problem.

Problem

Today, if a web site wants to create experiences involving local files (document editor, image compressor, etc.) they are at a disadvantage to native apps. A web site must ask the user to reopen a file every time they want to edit it. After opening, the site can only save changes by re downloading the file to the Downloads folder. A native app, by comparison, can maintain a most recently used list, auto save, and save files anywhere the user wants.

Use cases

  • Open local file to read
  • Open local file to edit and then save
  • Open local file to edit with auto save
  • Create and save a new file
  • Delete an existing file
  • Read meta data about files

Workarounds

  • FileSaver.js polyfills saveAs() from the [W3C File API], but files open in a new window instead of downloading on Safari 6.1+ and iOS.
  • In Edge, Firefox, and Chrome developers can:
    • Create a fake anchor element
    • Set the download attribute to the desired filename
    • Set href: to a data URI
    • Faking a click on the anchor element
  • Setting window.location to 'data:application/octet-stream' + data_stream
  • Hidden Flash controls to display a “save as” dialog

These methods are clunky and only support “save as”. They do not support most recently used lists, auto save, save, or deleting a file.


#2

It’d be nice to be able to request the user pick a file for editing, and that the file can be maintained open for reading and writing. It would be similar to what apps for Google Docs can do with documents in Drive, but on the local machine instead of in the cloud.


#3

How does this proposal compare with https://w3c.github.io/filesystem-api/? The use cases seem similar.


#4

That link says

agents are responsible for allocating space for the creation of a sandboxed file system and for imposing storage quotas on that virtual file system

It seems the difference in mine is that we’d be accessing actual files anywhere in the user’s file system, as allowed by the user, not in a virtual file system that is sandboxed in the browser.


#5

Yes, but that use case has been looked at often, is known to be one of the features that would be very useful, and has had several proposals fora way to do it as part of the work item, dating back most of a decade.

It’s also one that worries security people a lot in particular, which is one reason it hasn’t made it to an accepted standard yet, I think.


#6

That’s probably the reason, and it’s a lame one. I bet the first implementation would be more secure than what most average non-tech people get out of just having Windows (f.e. click here, download screensaver, boom, virus galore).

Android already let’s apps do this; android apps can access files limited to a specific folder by default. I’m sure it’s not difficult to let Chromium do it, but Google probably hasn’t prioritized it.


#7

What trusktr says is right - the FileSystem API is about sandboxed files owned by the browser. This proposal is meant to provide access to files on the device. We’ve run the proposal by some security folks here on the Chromium team and they think the model proposed should work.

The basic idea is that sites would only have access to files/directories that the user explicitly opened. Further, if the file changed outside of the site, it would need to reacquire the permission. User agents could decide whether they want to automatically grant any of these permissions or to show the user a permission dialog every time.


#8

@dknox Exactly! And, the user could tell the browser to remember the permission. Or, the browser could raise a prompt like “File XXX was modified externally, reload?” or similar.


#9

I agree that it is possible to deal with the security issues, and I really would like the functionality - when Opera had it, I could do lots of really useful stuff, albeit only for Opera users.

Yes, it needs to be restricted to files the user explicitly named. Allowing the app to suggest filenames like autorun.inf or .bashrc, to put files in dodgy places, or look for someone’s inbox, are the sort of phishing attacks that concern people who have looked at this. There’s also a supercookie-type fingerprinting vector, but I’m not sure that’s new and there are easier ways to do the same thing.

In reality I think a lot of this comes down to getting the security right in the UI - which means presenting risky actions to users in ways where they understand the risk. We are better at this than we were a decade ago, but we also understand the risks much better and I think that too makes us more cautious, as an industry.

The fact that native app platforms allow things that frighten the security daylights out of me doesn’t seem like a good reason for doing the same thing on the Web. But as I said, the functionality is very valuable, so I hope we can figure out a secure enough way to make it available that browsers do this.


#10

A permission prompt like “Allow this site to write to files and folders you open with it?” would be sufficient.


#11

Probably not.

In theory, it should be fine, but in practice permission prompts train people to click “yes” to everything, whether that is reasonable or not. Given the almost insatiable desire of the Web for tracking mechanisms, and the fact that any such permission given by the user could be reasonably argue to have been consent to recording information on the user’s machine in the same way as the EU now insists people do for cookies, it’s not unlikely that so many sites will ask for this permission that it becomes as meaningless as the fine print on a contract. Which leads to people clicking to agree to it without ever having read it - even if they have to scroll down pages of stuff before they are allowed to click. For example did you read this sentence? There is quite a lot of practical research on this, and it’s pretty clear that permission dialogs do not amount to getting informed consent for any interpretation of the term that assumes the person knows what they actually agreed to.

Further, there are parts of the file tree that are far more sensitive than others. It’s one thing to ask permission to read mbox files for an email application, another to read and write files that typically contain password information - even hashed, because given time those hashes are insecure - or set user preferences in ways that can be exploited for identity theft or the like.

That said, I don’t think people have come up with a very clear better answer, so the issue is about how to make sure the question asked is as focused as possible and the user gets as clear as possible a message that they should be thinking hard before offering this permission, or that it should be tightly circumscribed and relatively annoying to get into things that are sensitive.


#12

I find it hard to believe many sites will be asking users for the ability to write to files without apparent reason, and even if they do, they cannot do anything unless the user chooses a file. It seems like you are implying a way to arbitrarily access any files on the user’s computer.


Writable File API - status?
Writable File API - status?
#13

Currently, the proposal suggests that we may allow some method to save a new file to the device, which might allow the kind of tracking that @chaals mentions. @DanielHerr makes a good point that most of the other use cases would already require a specific user action. So maybe if we only showed a permission prompt to save a file that the user hadn’t already explicitly chosen?


#14

(Responding to the recent WICG proposal)

This is certainly an interesting problem from a security UX standpoint. There are a lot of potential ways for users to shoot themselves in the foot with a feature like this.

One thing I’d like to point out about the existing proposal is that preventing “executable” files from being written would make this API useless for many fields of software software development, as .js, .py, .rb, etc are all technically executable files (depending on what interpreters you have installed). An IDE that can’t edit source code files isn’t very useful.

And even with onerous restrictions like that, I think it’s going to be very hard if not impossible to prevent an app that has full write access to a software project directory from getting full user privileges on the user’s system. There are hundreds of different files where executable code (or equivalent) could potentially be sourced from in a typical software project (Makefiles, config files, dependency list files, etc) and I don’t think it’s practical to blacklist them all.

This API could indeed be useful for other domains, like photo editing. But I’m really struggling to see how we’d make it capable enough to build an IDE on top of without having to make unacceptable security trade-offs.


#15

I have some proposals on how to keep this a great feature but allow it to be flexible and solve all the goals:

Confirm data written to files

When a website wants to write to a file that you have selected the browser asks if you want to write this data to that specific file and you have to confirm. This to prevent the website from doing anything you don’t want it to, but still, allow the website to try.

By default create a new folder for each website

Like the Dropbox app way, there were two kinds of apps, one that would access your whole dropbox or one that would only be allowed to access a newly created folder for that specific app.

Confirm the magnitude of data giving to the website

I don’t believe we can prevent all things for happing, this kind of API’s already exist in Google Drive and Dropbox and so far we haven’t seen abuse of these systems to get all the users data. One solution would be to notify the user about how data is given to the website.

       "You are giving access to 10 folders and 7000 files, is that your intend?"

#16

I think if you limit the scope and confirm data written at the start, you can solve these problems, even better than current editors where people are installing extensions left and right :slight_smile:


#17

Is this single thread the right place to comment on the proposal? I anticipate it will generate a lot of controversy and it would be handy to have a place to debate issues by topic rather than all lumped together in sequence.

My first concern is whether full paths will be shared with the app provider. I consider paths sensitive metadata - they contain things like my username and, when well-organized, suggest what other information may be found alongside the files(s) I’m granting the website access to. e.g. A real estate agent might group files in subfolders named by property address or a medical practitioner by patient name. They might want to legitimately allow access to some content (e.g. annotate an x-ray using an image editor) without exposing information the site has no business knowing (like who’s x-ray it is). These are contrived examples but you get the idea.

One thing I like about the existing HTML file-picker is that all the website gets is the data I intend to give it; nothing more. I don’t want this new API leaking my pathnames or directory listings to the website (unless I give it access to an entire particular subdirectory tree).

Also how will permissions be maintained on an ongoing basis? i.e. How do I easily identify what files an app has access to, or conversely for a particular set of files, what apps have rights? Do you intend to integrate with the client OS file properties tabs, or are you going to duplicate something akin to those efforts in the browser?

Regarding @KevinSimper’s suggestion of giving each website its own folder - that’s great from a security perspective, but terrible from a useability / organizational perspective as it forces me to hierarchize by application rather than by content relevance or meaning.


#18

Here’s an idea to avoid leaking path and file names:

var file = window.promptSelectFile(..., access:read)
document.getElementById('filename').style.secureRender = file.token

<div id='status'>
  Editing: <span id='filename' style='path-format:title'>
</div>

The file object supports everything you’d expect (read, write, etc), but doesn’t reveal local paths to the website. Instead it provides an obfuscated token derived by the user agent (e.g. perhaps by encrypting the original full pathname with a site-specific key, or associating each file with a persisted ID).

A new secure-render attribute lets the designer create placeholders for the sensitive data anywhere in the HTML content. The browser converts the given token to its corresponding value when the page is rendered, but in such a way that if the site tries to inspect the content all it gets back is the obfuscated tag.

Mechanisms are provided to control how the value is formatted and localize it into the semantics of the native OS. path-format could be:

full       // C:\Users\Alice\Documents\Patients\JohnSmith\XRay.png
directory  // C:\Users\Alice\Documents\Patients\JohnSmith
name       // XRay.png
title      // XRay
extension  // png

I can now build a full-fledged, browser-based file manager without needing to know any pathnames.

Do browsers today have any sort of “placeholder” mechanism like this for websites to display sensitive local data without having to know its content? Can you think of additional use cases where this might be helpful?


#19

It may make sense to have a dialog for every file or folder the user chooses containing options such as whether to allow writable, persistent, and full path access.


#20

We have a slightly tangential usecase. We encrypt files and convert them to .html files where the original encrypted content is saved as comment blocks. A .docx file becomes .docx.html. Users typically double click to open this file in browser and we can allow them editing by transferring the contents to an iframe within the file itself. We would like to have an ability to save back to the parent file location from within the iframe or from within the js running in the parent file:// context.