Search code examples
javafilenio2

Why can we change the file attributes of a read-only file in Java?


Consider the following code:

import java.io.IOException;
import java.nio.file.attribute.DosFileAttributeView;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileTime;
import java.time.Instant;

public class Word {
    public static void main(String[] args){

        try{
            Path path = Paths.get("readonly.txt");
            Files.createFile(path);
            DosFileAttributeView dos = Files.getFileAttributeView(path,DosFileAttributeView.class);
            dos.setReadOnly(true);

            //Files.delete(path); Access denied exception

            dos.setHidden(true);            //can change attributes all we want
            dos.setTimes(null,FileTime.from(Instant.now()),null);
            dos.setReadOnly(false);

            Files.delete(path);
        }
        catch(IOException e){
            e.printStackTrace();
        }


    }
}

Naturally , trying to modify the read-only file will give us an AccessDeniedException. However, as shown in the code , that doesn't apply for the attributes of the file, which can be modified all we want.

Of course that means that anyone can easily just change the read-only attribute back to false and modify the file all they want.

So, how come this is allowed, and how would someone create an actual read-only file in Java?


Solution

  • Security of Windows files is controlled by the security descriptor on the file.

    Of course that means that anyone can easily just change the read-only attribute back to false and modify the file all they want.

    Not 'anyone' - only those people who have permission (see below) can do it. If you created the file, then it's not surprising that you can do what you want. Generally speaking though, I'd expect that other users (who are not administrators) would not be able to affect your files by default.

    Who can change DOS attributes is controlled via the security descriptor - specifically by granting FILE_WRITE_ATTRIBUTES access or not. Naturally, it has to be possible for someone to clear the DOS read-only attribute, otherwise... once a file was marked read-only, there would be no way back. Generally, if you create a file, you'll have total control over it.

    Whether a given user or group of users can write data to the file is controlled by the FILE_WRITE_ACCESS bit (and maybe some others, but this is an introductory answer) in an access mask. If you don't grant write access to users, they can't write. If you really want to prevent someone from writing to the file, this is how you do it.

    The DOS 'read only' attribute exists for compatibility and may be useful as a hint that really you don't want to write to this file, but it is not a security restriction.

    None of this is really anything to do with Java, it's how the file system in the OS works. You can examine the security settings on a file with Windows Explorer.