3939import java .io .File ;
4040import java .io .IOException ;
4141import java .io .InputStream ;
42+ import java .nio .file .FileSystems ;
4243import java .nio .file .Files ;
44+ import java .nio .file .Path ;
4345import java .nio .file .StandardCopyOption ;
46+ import java .nio .file .attribute .AclEntry ;
47+ import java .nio .file .attribute .AclEntryPermission ;
48+ import java .nio .file .attribute .AclEntryType ;
49+ import java .nio .file .attribute .AclFileAttributeView ;
50+ import java .nio .file .attribute .PosixFilePermissions ;
51+ import java .nio .file .attribute .UserPrincipal ;
4452import java .util .ArrayList ;
53+ import java .util .Collections ;
54+ import java .util .Comparator ;
4555import java .util .List ;
4656import java .util .StringJoiner ;
57+ import java .util .stream .Stream ;
58+
4759import org .apache .pdfbox .debugger .PDFDebugger ;
4860
4961/**
@@ -58,6 +70,84 @@ public class Tree extends JTree
5870 private final JPopupMenu treePopupMenu ;
5971 private final Object rootNode ;
6072
73+ // Temporary files are stored in a private temp directory with restricted permissions,
74+ // which is deleted on exit using a shutdown hook.
75+ // PDFBOX-6185
76+ private static final Path TEMP_DIR = createTempDir ();
77+
78+ private static Path createTempDir ()
79+ {
80+ try
81+ {
82+ Path tempDir = Files .createTempDirectory ("pdfbox-" );
83+ applyOwnerOnlyPermissions (tempDir );
84+
85+ // use shutdown hook instead of deleteOnExit() to ensure deletion
86+ // of the entire directory in case of not automatically deleted on
87+ // JVM exit (e.g. due to hard crash or kill -9)
88+ Runtime .getRuntime ().addShutdownHook (new Thread (() ->
89+ {
90+ try (Stream <Path > entries = Files .walk (tempDir ))
91+ {
92+ entries .sorted (Comparator .reverseOrder ())
93+ .forEach (p -> p .toFile ().delete ());
94+ }
95+ catch (IOException ignored ) {}
96+ }));
97+
98+ return tempDir ;
99+ }
100+ catch (IOException e )
101+ {
102+ throw new RuntimeException ("Failed to create temporary directory for PDFDebugger" , e );
103+ }
104+ }
105+
106+ private static void applyOwnerOnlyPermissions (Path dir ) throws IOException
107+ {
108+ if (FileSystems .getDefault ().supportedFileAttributeViews ().contains ("posix" ))
109+ {
110+ // Unix/macOS — rwx------
111+ Files .setPosixFilePermissions (dir , PosixFilePermissions .fromString ("rwx------" ));
112+ }
113+ else
114+ {
115+ // Windows — replace the entire ACL with a single owner-only ALLOW entry
116+ AclFileAttributeView aclView =
117+ Files .getFileAttributeView (dir , AclFileAttributeView .class );
118+
119+ if (aclView == null )
120+ {
121+ throw new IOException ("Neither posix nor ACL view is supported on this file system" );
122+ }
123+
124+ UserPrincipal owner = aclView .getOwner ();
125+
126+ AclEntry ownerFullControl = AclEntry .newBuilder ()
127+ .setType (AclEntryType .ALLOW )
128+ .setPrincipal (owner )
129+ .setPermissions (
130+ AclEntryPermission .READ_DATA ,
131+ AclEntryPermission .WRITE_DATA ,
132+ AclEntryPermission .APPEND_DATA ,
133+ AclEntryPermission .READ_NAMED_ATTRS ,
134+ AclEntryPermission .WRITE_NAMED_ATTRS ,
135+ AclEntryPermission .EXECUTE ,
136+ AclEntryPermission .DELETE_CHILD ,
137+ AclEntryPermission .READ_ATTRIBUTES ,
138+ AclEntryPermission .WRITE_ATTRIBUTES ,
139+ AclEntryPermission .DELETE ,
140+ AclEntryPermission .READ_ACL ,
141+ AclEntryPermission .WRITE_ACL ,
142+ AclEntryPermission .SYNCHRONIZE
143+ )
144+ .build ();
145+
146+ // Set so that only the owner has permissions, and remove any inherited ACL entries
147+ aclView .setAcl (Collections .singletonList (ownerFullControl ));
148+ }
149+ }
150+
61151 /**
62152 * Constructor.
63153 */
@@ -295,8 +385,7 @@ private JMenuItem getFileOpenMenu(final COSStream cosStream, final TreePath node
295385 {
296386 try
297387 {
298- File temp = Files .createTempFile ("pdfbox" , "." + extension ).toFile ();
299- temp .deleteOnExit ();
388+ File temp = Files .createTempFile (TEMP_DIR , "pdfbox" , "." + extension ).toFile ();
300389
301390 try (InputStream is = cosStream .createInputStream ())
302391 {
0 commit comments