Firefox 3.6/HTML5 File Objects Security Review
From MozillaWiki
Contents
Overview
Currently, an entirely new spec is being drafted for file objects and handling within HTML5. It will provide a much more robust interface for accessing content in local files, in addition to extending functionality for file objects within Javascript/DOM. The primary additions include:
- Drag n' drop of local files into a web page [Bug 503598]
- Asynchronous file data access via callback methods [Bug 507805]
- Sending file objects via XMLHttpRequest [Bug 491201]
- Improved file dialog window that allows for multiple file selection and file-type filtering (bug pending)
- Manipulating files with JS worker threads via postMessage (bug pending)
- Storing file objects within the localStorage/sessionStorage APIs (aaaaand bug pending)
(Keep in mind that the features above may change as the spec matures.)
For more details, consult the latest HTML5 file draft: http://dev.w3.org/2006/webapi/FileUpload/publish/FileAPI.xhtml
Security and Privacy
- Include a thorough description of the security assumptions, capabilities and any potential risks (possible attack points) being introduced by your project.
- There was talk within the spec about the (previously modal) FileDialog constructed perpetually within a non-terminating loop and harassing the user to choose a file. There should be a number of fairly straightforward ways to circumvent the issue, one of which includes making the new FileDialog window NOT modal (or perhaps tab-modal).
- With regards to file drag n' drop, there was talk about the possibility that an unintentional drag without an ending drop could cause unwarranted and unexpected access of a user's file data. For instance, imagine some extension having proper privileges to execute chrome code. If a user dragged code from one side of the desktop to the other side, and passed through the browser window, the chrome caller would be able to detect a drag event and instantiate a DOMFile object and extract a file's contents, all without the user's knowledge. This issue was alleviated by populating the .files attribute of a dataTransfer *only* on a drop event, and not on a dragstart event, making it less likely a user could ever inadvertently give up file data.
- Large files (on the order of several 100's of MB) are a bit of a predicament. If a user decides to pass them in for whatever inane reason, the browser stalls as it tries in vain to store all the data in memory, only to receive malloc failure after malloc failure ad nauseum. Of course, the stalling time is somewhat alleviated by the cancelReads functionality, but the malloc failure unfortunately isn't. Not really certain what security threat this shortcoming could pose, but it does seem like malicious things could arise from it.
- CancelReads makes me suspicious, in that I have an inkling (i.e. without any demonstrable evidence) that some specific ordering of getFileContent() and cancelReads() calls can mess up memory management. This is only a suspicion, admittedly, but I do want to scrutinize this function as extensively as possible.
Exported APIs
- Please provide a table of exported interfaces (APIs, ABIs, protocols, UI, etc.) The new File API (re)defines nsIDOMFile and defines a new nsIDOMFileError and nsIDOMFileDialog. nsIDOMFileList remains entirely untouched. Check out the interface definitions at the HTML5 file spec here.
- Are the externally visible interfaces documented clearly enough for a non-Mozilla developer to use them successfully? Yes, assuming all of it were to be implemented. But right now, we're holding on implementing the splice/fileURL functionality and all the interface niceties that go along with it (e.g. the distinction between a File and FileData, a SPLICE_ERR error code, etc.). Any developer expecting those functions would be justifiably perplexed.
- Does it change any existing interfaces? Yes, those working with nsDOMFile objects expecting old-style behavior will likely discover the following:
- getAsText will no longer work synchronously (though the other synchronous functions, getAsDataURL and getAsBinary, survived)
- data accessor functions are now asynchronous and thus require a callback handler
- fileName and fileSize attributes are now called name and size, respectively
- mediaType is a new attribute that returns, surprisingly enough, the MIME type represented by the file object
Module interactions
- What other modules are used (REQUIRES in the makefile, interfaces)? The new File will interact with (and thus change the interfaces to):
- nsIDOMDataTransfer
- nsIXMLHttpRequest
- nsIDOMWorkers
- nsIDOMStorage
Data
- What data is read or parsed by this feature? Currently, any file the user chooses (be it through Drag 'N Drop or the FileDialog) can be initialized as a DOMfile object. There are no restrictions whatsoever on which file types can be accessed.
- What is the output of this feature? From a local file, a File object can be created, from which its contents can be obtained as text, a data URL or a binary string.
Reliability
- What failure modes or decision points are presented to the user? As far as I know, there are plans to prompt the user with a non-modal dialogue alerting them when file retrieval occurs via drag n' drop, though none of the details are currently fleshed out in the spec. Perhaps this an indication that such a feature is up to the browser vendor?
- Can its files be corrupted by failures? Does it clean up any locks/files after crashes? Other than storing/retrieving files within DOMStorage, there's no mechanism defined for writing to a user's local file system. And there probably won't be anytime soon.
Review comments
- Currently people who drag a desktop file and drop it into a browser window (all browsers, not just Firefox) will have the page contents replaced by the new file -- they aren't giving the file contents to the old page. This will change that expectation. Need some front-end signifier that there's a change in behavior/expectation. Cursor change? Drop target in page? A popup confirmation dialog? (kidding) Maybe it would be OK to drop "replace current contents" behavior and have file-drop always provide the file to the given page? Probably a good idea to talk about UX people about this and find out whether or not we can do both.
- Page gets info about file. Should not include path (currently doesn't), name, size, type (not content-sniffed) and extension is OK.
- only transfer data between pages with the same principal
- once a page gets a "DOMFile" reference it can read that file as long as the page is open, including any future edits during that time. This may be counter-intuitive to users who expect pages to get a "copy" of the file when it's dropped/submitted.
- <jesse> allowing file drops turns window.moveTo into a security hole. maybe fixing https://bugzilla.mozilla.org/show_bug.cgi?id=502561 needs to block supporting file drops.
- <script> should not be allowed to load from filedata: -- could we even limit its use to images?
- If files are sent cross-origin via postMessage() the new origin gets access to the file, not just a snap-shot. This seems bad. Not much different than one page sending updated contents to another which they could do now with strings, but the "lifetime of accessibility" would be non-intuitive to users. Closing the page to which they gave access doesn't necessarily stop access to the contents (as opposed to a copy of the data given).
- jst thinks we should invalidate file handles if the file changes on disk.
- storing files into globalStorage should probably be a copy of the file, not a handle to the live local file. Otherwise if this is some off-line app and the user deletes the local file after "uploading" it the file could be gone.