JDK-4802383 : JFileChooser makes unecessary security checks
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.0
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2003-01-13
  • Updated: 2010-08-10
  • Resolved: 2010-08-10
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7Resolved
Related Reports
Relates :  
Description
Name: jk109818			Date: 01/13/2003


FULL PRODUCT VERSION :
java version "1.4.0_02"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0_02-b02)
Java HotSpot(TM) Client VM (build 1.4.0_02-b02, mixed mode)


FULL OPERATING SYSTEM VERSION :

Linux vader.cs.columbia.edu 2.4.18-10 #1 Wed Aug 7 11:39:21
EDT 2002 i686 unknown

ADDITIONAL OPERATING SYSTEMS :

glibc-kernheaders-2.4-7.16
glibc-2.2.5-40
glibc-common-2.2.5-40
glibc-devel-2.2.5-40

Red Hat Linux release 7.3 (Valhalla)


A DESCRIPTION OF THE PROBLEM :
JFileChooser makes two unecessary security checks that
prevent programs using tailored security policies from using it:

(1) It requires permission to read "user.home", even when
the initial directory has been specified using the
JFileChooser(File) constructor

(2) It requires a write permission for the directory even if
it is only going to be used for opening a file

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1.Create policy file (note that you if you remove the
property permission, it will bomb earlier)

grant {
  permission java.io.FilePermission "/home/akonstan/test",
"read";
  permission java.io.FilePermission "/home/akonstan/test/-",
"read";
  permission java.util.PropertyPermission "*", "read";
};


2.Compile the sample code
3.java -Djava.security.manager
-Djava.security.policy=read.policy JFileChooserSecurityBug

EXPECTED VERSUS ACTUAL BEHAVIOR :
Have the file chooser open instead of throwing a security
exception.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.security.AccessControlException: access denied
(java.io.FilePermission /n/sutton/u/sutton/akonstan/test write)
        at
java.security.AccessControlContext.checkPermission(AccessControlContext.java:270)
        at java.security.AccessController.checkPermission(AccessController.java:401)
        at java.lang.SecurityManager.checkPermission(SecurityManager.java:542)
        at java.lang.SecurityManager.checkWrite(SecurityManager.java:975)
        at java.io.File.canWrite(File.java:658)
        at sun.awt.shell.ShellFolder.canWrite(ShellFolder.java:251)
        at
javax.swing.plaf.metal.MetalFileChooserUI.doDirectoryChanged(MetalFileChooserUI.java:1333)
        at
javax.swing.plaf.metal.MetalFileChooserUI.access$2600(MetalFileChooserUI.java:35)
        at
javax.swing.plaf.metal.MetalFileChooserUI$12.propertyChange(MetalFileChooserUI.java:1438)
        at
javax.swing.event.SwingPropertyChangeSupport.firePropertyChange(SwingPropertyChangeSupport.java:264)
        at
javax.swing.event.SwingPropertyChangeSupport.firePropertyChange(SwingPropertyChangeSupport.java:232)
        at javax.swing.JComponent.firePropertyChange(JComponent.java:3801)
        at javax.swing.JFileChooser.setCurrentDirectory(JFileChooser.java:541)
        at
javax.swing.plaf.metal.MetalFileChooserUI$DirectoryComboBoxAction.actionPerformed(MetalFileChooserUI.java:1846)
        at javax.swing.JComboBox.fireActionEvent(JComboBox.java:1196)
        at javax.swing.JComboBox.contentsChanged(JComboBox.java:1267)
        at
javax.swing.AbstractListModel.fireContentsChanged(AbstractListModel.java:100)
        at
javax.swing.plaf.metal.MetalFileChooserUI$DirectoryComboBoxModel.setSelectedItem(MetalFileChooserUI.java:1710)
        at
javax.swing.plaf.metal.MetalFileChooserUI$DirectoryComboBoxModel.addItem(MetalFileChooserUI.java:1681)
        at
javax.swing.plaf.metal.MetalFileChooserUI$DirectoryComboBoxModel.access$2300(MetalFileChooserUI.java:1611)
        at
javax.swing.plaf.metal.MetalFileChooserUI.doDirectoryChanged(MetalFileChooserUI.java:1330)
        at
javax.swing.plaf.metal.MetalFileChooserUI.access$2600(MetalFileChooserUI.java:35)
        at
javax.swing.plaf.metal.MetalFileChooserUI$12.propertyChange(MetalFileChooserUI.java:1438)
        at
javax.swing.event.SwingPropertyChangeSupport.firePropertyChange(SwingPropertyChangeSupport.java:264)
        at
javax.swing.event.SwingPropertyChangeSupport.firePropertyChange(SwingPropertyChangeSupport.java:232)
        at javax.swing.JComponent.firePropertyChange(JComponent.java:3801)
        at javax.swing.JFileChooser.setCurrentDirectory(JFileChooser.java:541)
        at javax.swing.JFileChooser.<init>(JFileChooser.java:333)
        at javax.swing.JFileChooser.<init>(JFileChooser.java:288)
        at JFileChooserSecurityBug.main(JFileChooserSecurityBug.java:42)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.io.*;
import javax.swing.*;
import javax.swing.filechooser.*;

/**
 * Demonstrate bug in JFileChooser which requires "write" file
 * access even though only the open functionality needs to be
 * used.
 * <p>
 * To execute, create a file called "read.policy" containing (change the
 * directory to some location of your preference).
 * <p>
 * <pre>
 * grant {
 *   permission java.io.FilePermission "/home/akonstan/test", "read";
 *   permission java.io.FilePermission "/home/akonstan/test/-", "read";
 *   permission java.util.PropertyPermission "*", "read";
 * };
 * <pre>
 * <p>
 * Then execute as shown below:
 * <p>
 * <pre>
 * mkdir test
 * touch test/myfile.txt
 * javac JFileChooserSecurityBug.java
 * java -Djava.security.manager -Djava.security.policy=read.policy
JFileChooserSecurityBug
 * </pre>
 */
public class JFileChooserSecurityBug {
  public static void main(String[] args) throws Exception {
    //
    // Demonstrate that program can list the files in the directory
    //
    File dir = new File("/home/akonstan/test");
    File[] files = dir.listFiles();
    for(int i=0; i<files.length; i++) {
      System.out.println("File: " + files[i]);
    }

    //
    // Constructor triggers security exception
    //
    JFileChooser chooser = new JFileChooser("/home/akonstan/test");
    
    //
    // Even though all we want to show is an open dialog (no write)
    //
    chooser.showOpenDialog(null);
  }
}

---------- END SOURCE ----------

CUSTOMER WORKAROUND :
1. Provide permission to read the user.dir property.

2. Provide a subclass to java.io.File whose canWrite()
method returns false without checking the security manager
(Review ID: 165767) 
======================================================================

Comments
PUBLIC COMMENTS In the CR description was described couple problems: (1) It requires permission to read "user.home", even when the initial directory has been specified using the JFileChooser(File) constructor Answer: It's a duplicate of CR 6216982 (2) It requires a write permission for the directory even if it is only going to be used for opening a file Answer: that bug was fixed by CR 4847375
10-08-2010

WORK AROUND The following might help (untested): JFileChooser chooser = new JFileChooser(new ReadOnlyFile(startPath)); [...] private static class ReadOnlyFile extends File { public ReadOnlyFile(String path) { super(path); } public boolean canWrite() { return false; } public File[] listFiles() { File[] files = super.listFiles(); if (files != null) { for (int i = 0; i < files.length; i++) { files[i] = new ReadOnlyFile(files[i].getAbsolutePath()); } } return files; } public File getParentFile() { File parent = super.getParentFile(); if (parent != null) { parent = new ReadOnlyFile(parent.getAbsolutePath()); } return parent; } } ###@###.### 2003-06-20
20-06-2003

EVALUATION The JFileChooser UI classes need to catch AccessControlException and treat it as canWrite() == false. Also need to use privileged code for getting properties. ###@###.### 2003-06-20
20-06-2003