1111import org .fugerit .java .doc .project .facade .flavour .ProcessEntry ;
1212
1313import java .io .*;
14+ import java .nio .file .Path ;
1415import java .util .HashMap ;
1516import java .util .Map ;
1617
@@ -19,6 +20,18 @@ public class FeatureFacade {
1920
2021 private FeatureFacade () {}
2122
23+ /**
24+ * Checks that the given file is inside the baseFolder after normalization.
25+ * Throws IOException if not.
26+ */
27+ public static void checkIfInBaseFolder (File baseFolder , File file ) throws IOException {
28+ Path base = baseFolder .getCanonicalFile ().toPath ().normalize ();
29+ Path target = file .getCanonicalFile ().toPath ().normalize ();
30+ if (!target .startsWith (base )) {
31+ throw new IOException ( String .format ( "File path %s is not within permitted base folder %s" , file .getCanonicalPath (), baseFolder .getCanonicalPath () ) );
32+ }
33+ }
34+
2235 public static void copyFlavourList ( File baseFolder , String actualFlavour ) throws IOException {
2336 copyResourcesList ( baseFolder , "flavour" , actualFlavour );
2437 }
@@ -37,16 +50,25 @@ private static void copyResourcesList( File baseFolder, String mode, String id )
3750 }
3851 }
3952
40- protected static void insureParent ( File file ) throws IOException {
53+ public static void insureParent ( File file ) throws IOException {
4154 File parentFile = file .getParentFile ();
42- if ( !parentFile .exists () ) {
43- log .info ( "creates parent directory {}, mkdirs:? {}" , parentFile .getCanonicalPath (), parentFile .mkdirs () );
55+ // Defensive: check parent is within project's root as well
56+ if (parentFile != null ) {
57+ File baseFolder = file .getParentFile ().getParentFile ();
58+ if (baseFolder != null ) {
59+ checkIfInBaseFolder (baseFolder , parentFile );
60+ }
61+ if ( !parentFile .exists () ) {
62+ log .info ( "creates parent directory {}, mkdirs:? {}" , parentFile .getCanonicalPath (), parentFile .mkdirs () );
63+ }
4464 }
4565 }
4666
4767 protected static void copyFile (String path , File baseFolder , String basePath ) {
4868 SafeFunction .apply ( () -> {
4969 File outputFile = new File ( baseFolder , path );
70+ // Validate that the output file is inside the intended base folder
71+ checkIfInBaseFolder (baseFolder , outputFile );
5072 insureParent ( outputFile );
5173 String fullPath = basePath +path ;
5274 log .info ( "copy path '{}' to file '{}'" , fullPath , outputFile .getCanonicalPath () );
0 commit comments