This is a reasonable question to ask, because it's not immediately apparent why merely letting websites open arbitrary file URLs is bad in the same way that letting websites read arbitrary file URLs is bad. Here's a summary:
A malicious website can read arbitrary files on disk by opening a file://
URL if the file://
URL points to a malicious HTML file on disk. Browsers and other applications sometimes cache untrusted HTML as a file on disk.
Browsers don't always perfectly enforce the same-origin policy, and bugs in the same-origin policy can allow arbitrary file access if all file://
URLs are considered to have the same origin.
Some file://
URLs can cause malicious effects just by allowing the browser to open them.
Here's the long-winded explanation with quoted sources:
These are the holes caused by letting sites link to local files:
A1. If the browser or any helper app (e.g. RealPlayer) puts untrusted files
in a predictable location, any page can link to that file and thus read every
file on your hard drive.
A2. Holes in same-origin policy (cross-domain) become
read-any-file-on-your-hard-drive holes.
But same-origin holes are already considered serious enough to block releases
(they let sites steal cookies, passwords, and info on intranet web servers).
A3. DoS attacks against the browser or even the OS using file:///con/con or
/dev/stuff.
https://bugzilla.mozilla.org/show_bug.cgi?id=84128#c190
These issues are still relevant today with e.g. the 2017 exploit in Firefox for Android that allowed a malicious website to read files from /sdcard/Download/
(CVE-2017-7759).
Android intent URLs given to Firefox for Android can be used to navigate from
HTTP or HTTPS URLs to local "file:" URLs, allowing for the reading of local
data through a violation of same-origin policy.
https://nvd.nist.gov/vuln/detail/CVE-2017-7759
Steps to reproduce:
Visit an remote (http) webpage:
<script>
location="intent:file:///(path)#Intent;type=text/html;end";
</script>
Actual results:
The JS code above redirects the user to file: URL.
The redirection allows remote pages to exfiltrate files in /sdcard/Download/.
https://bugzilla.mozilla.org/show_bug.cgi?id=1356893
The browser security handbook gives a good explanation of the more general rationale:
In the case of file:
, web sites are generally prevented from navigating to
local resources at all. The three explanations given for this decision are as
follows:
Many browsers and browser plugins keep their temporary files and cache data
in predictable locations on the disk. The attacker could first plant a HTML
file in one these spots during normal browsing activities, and then attempt
to open it by invoking a carefully crafted file:///
URL. As noted
earlier, many implementations of same-origin policies are eager to bestow
special privileges on local HTML documents (more), and so this led to
frequent trouble.
Users were uncomfortable with random, untrusted sites opening local,
sensitive files, directories, or applications within <IFRAME>
containers,
even if the web page embedding them technically had no way to read back the
data - a property that a casual user could not verify.
Lastly, tags such as <SCRIPT>
or <LINK REL="stylesheet" HREF="...">
could be used to read back certain constrained formats of local files from
the disk, and access the data from within cross-domain scripts. Although no
particularly useful and universal attacks of this type were demonstrated,
this posed a potential risk.
https://code.google.com/archive/p/browsersec/wikis/Part2.wiki
So the browser does its best to enforce the same-origin policy, but it doesn't always succeed, as demonstrated by the Firefox for Android bug and more generally the existence of XSS vulnerabilities.
Furthermore, because of cache files, remote files can possess real file://
URLs. Browsers are careful to make profiles and cache filenames unpredictable, but all it takes is one untrusted file in a known location and it's game over. Even if malicious remote Javascript can't directly access the filesystem, it can affect cache files and cookies.
if someone can cause a file to be downloaded to your machine (in a cache
file, or by having the user consent to download it to a known directory), and
the downloaded file contains JS, then referencing it via a file: URL on a
hostile web page would cause the JS to be run, and since it's coming from the
local drive, it would run with privileges.
https://bugzilla.mozilla.org/show_bug.cgi?id=40538
if an attacker can cause content to be placed on the user's hard drive, for
example by setting a cookie, stuffing the cache, etc., and can cause that
content to execute in the browser, then that content can communicate
information back to the attacker, one way or another.
https://bugzilla.mozilla.org/show_bug.cgi?id=101207
It's also worth asking: what should "same origin" mean for a file://
URL? Should it be just that file's directory and its subdirectories, or should it be the entire filesystem?
In Gecko 1.8 or earlier, any two file:
URIs are considered to be
same-origin. In other words, any HTML file on your local disk can read any
other file on your local disk.
Starting in Gecko 1.9, files are allowed to read only certain other files.
Specifically, a file can read another file only if the parent directory of
the originating file is an ancestor directory of the target file.
Directories cannot be loaded this way, however.
https://developer.mozilla.org/en-US/docs/Archive/Misc_top_level/Same-origin_policy_for_file:_URIs
Finally, note that a malicious script with the ability to instruct the browser to load a file can cause harm even without the ability to read the file. Loading arbitrary file://
URLs can be used to crash the browser or interfere with keyboard input.
Not all URI loads are safe. For example, loading some file: URIs can hang the
browser or even crash the operating system in some cases.
https://developer.mozilla.org/en-US/docs/Archive/Mozilla/Safely_loading_URIs
the server doesn't need to be able to read the result of the load to cause
damage. On some Win98 systems, loading file:///C:/con/con
causes a crash
and data loss. Similar results could come from accessing something in
file:///dev/*
on Unix, and I believe similar problems exist on Mac as well.
https://bugzilla.mozilla.org/show_bug.cgi?id=101207
The following HTML will cause Mozilla (and Netscape 4.77) to open /dev/tty0,
which will cause all keyboard input from /dev/tty0 to be eaten:
<img src="file:///dev/tty0">
I suggest that Mozilla should never attempt to open a file URI when the
content has been loaded via something other than file (http, https, ftp,
etc).
https://bugzilla.mozilla.org/show_bug.cgi?id=91316
As an example, on Unix systems, clicking a link like <A HREF="file:///dev/zero">
will cause the browser to start writing an infinitely large file of zeros. There are similar problems on Windows.
https://bugzilla.mozilla.org/show_bug.cgi?id=47988
Related questions:
Are there any know browsers that support file URL redirection?
Same-origin policy for file: URLs in Android browser?
Can malicious Javascript in local HTML -file send files to internet in Firefox/Chrome?