Skip to content

Commit 543f6ae

Browse files
committed
fix: security path accessor
1 parent 548867c commit 543f6ae

12 files changed

Lines changed: 135 additions & 20 deletions

File tree

api/src/main/java/com/instancify/scriptify/api/script/security/ScriptSecurityManager.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ public interface ScriptSecurityManager {
2222
*/
2323
void setSecurityMode(boolean securityMode);
2424

25+
/**
26+
* Receives security file system.
27+
*
28+
* @return Security file system
29+
*/
30+
SecurityFileSystem getFileSystem();
31+
2532
/**
2633
* Receives security path accessor.
2734
*
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.instancify.scriptify.api.script.security;
2+
3+
import java.io.File;
4+
import java.nio.file.Path;
5+
6+
/**
7+
* Provides secure access to files and paths, ensuring
8+
* all operations are restricted to the configured base path.
9+
*/
10+
public interface SecurityFileSystem {
11+
12+
/**
13+
* Returns a secure Path inside the base path.
14+
*
15+
* @param path the path string to resolve
16+
* @return a normalized and secure Path
17+
* @throws SecurityException if the path is outside basePath or not accessible
18+
*/
19+
Path getPath(String path);
20+
21+
/**
22+
* Returns a secure File inside the base path.
23+
*
24+
* @param path the path string to resolve
25+
* @return a normalized and secure File
26+
* @throws SecurityException if the path is outside basePath or not accessible
27+
*/
28+
File getFile(String path);
29+
30+
/**
31+
* Returns the base path for this file system.
32+
*/
33+
Path getBasePath();
34+
}

core/src/main/java/com/instancify/scriptify/core/script/function/impl/file/ScriptFunctionDeleteFile.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ public Object invoke(Script<?> script, ScriptFunctionArgument[] args) throws Scr
3030
}
3131

3232
if (args.length == 1) {
33-
return new File(filePath).delete();
33+
return script.getSecurityManager().getFileSystem().getFile(filePath).delete();
3434
}
3535

3636
if (!(args[1].getValue() instanceof Boolean recursive)) {
3737
throw new ScriptFunctionArgTypeException(Boolean.class, args[1].getType());
3838
}
3939

40-
File file = new File(filePath);
40+
File file = script.getSecurityManager().getFileSystem().getFile(filePath);
4141
if (recursive) {
4242
return deleteDirectoryRecursively(file);
4343
} else {

core/src/main/java/com/instancify/scriptify/core/script/function/impl/file/ScriptFunctionDownloadFromUrl.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
import java.io.File;
1212
import java.io.IOException;
1313
import java.io.InputStream;
14-
import java.net.URL;
14+
import java.net.URI;
15+
import java.net.URISyntaxException;
1516
import java.nio.file.Files;
1617

1718
/**
@@ -37,11 +38,11 @@ public Object invoke(Script<?> script, ScriptFunctionArgument[] args) throws Scr
3738
throw new ScriptFunctionArgTypeException(String.class, args[1].getType());
3839
}
3940

40-
try (InputStream in = new URL(url).openStream()) {
41-
File targetPath = new File(filePath);
41+
try (InputStream in = new URI(url).toURL().openStream()) {
42+
File targetPath = script.getSecurityManager().getFileSystem().getFile(filePath);
4243
Files.copy(in, targetPath.toPath());
43-
} catch (IOException e) {
44-
e.printStackTrace();
44+
} catch (IOException | URISyntaxException e) {
45+
throw new RuntimeException(e);
4546
}
4647

4748
return null;

core/src/main/java/com/instancify/scriptify/core/script/function/impl/file/ScriptFunctionExistsFile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class ScriptFunctionExistsFile implements ScriptFunction {
2525
public Object invoke(Script<?> script, ScriptFunctionArgument[] args) throws ScriptFunctionException {
2626
if (args.length == 1) {
2727
if (args[0].getValue() instanceof String filePath) {
28-
return Files.exists(Path.of(filePath));
28+
return Files.exists(script.getSecurityManager().getFileSystem().getPath(filePath));
2929
} else {
3030
throw new ScriptFunctionArgTypeException(String.class, args[0].getType());
3131
}

core/src/main/java/com/instancify/scriptify/core/script/function/impl/file/ScriptFunctionListFiles.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
import org.jetbrains.annotations.NotNull;
1010

1111
import java.io.File;
12-
import java.nio.file.Paths;
1312
import java.util.Arrays;
13+
import java.util.Objects;
1414

1515
/**
1616
* Represents a function to get all files in a folder
@@ -26,9 +26,9 @@ public class ScriptFunctionListFiles implements ScriptFunction {
2626
public Object invoke(Script<?> script, ScriptFunctionArgument[] args) throws ScriptFunctionException {
2727
if (args.length == 1) {
2828
if (args[0].getValue() instanceof String filePath) {
29-
File folder = Paths.get(filePath).toAbsolutePath().toFile();
29+
File folder = script.getSecurityManager().getFileSystem().getFile(filePath);
3030
if (folder.isDirectory()) {
31-
return Arrays.stream(folder.listFiles()).map(File::getAbsolutePath).toList();
31+
return Arrays.stream(Objects.requireNonNull(folder.listFiles())).map(File::getAbsolutePath).toList();
3232
} else {
3333
throw new ScriptFunctionException("File is not a folder");
3434
}

core/src/main/java/com/instancify/scriptify/core/script/function/impl/file/ScriptFunctionMoveFile.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public Object invoke(Script<?> script, ScriptFunctionArgument[] args) throws Scr
3333
throw new ScriptFunctionArgTypeException(String.class, args[1].getType());
3434
}
3535

36-
File fileToMove = new File(originalFilePath);
37-
return fileToMove.renameTo(new File(targetFilePath));
36+
File fileToMove = script.getSecurityManager().getFileSystem().getFile(originalFilePath);
37+
return fileToMove.renameTo(script.getSecurityManager().getFileSystem().getFile(targetFilePath));
3838
}
3939
}

core/src/main/java/com/instancify/scriptify/core/script/function/impl/file/ScriptFunctionReadFile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public Object invoke(Script<?> script, ScriptFunctionArgument[] args) throws Scr
2727
if (args.length == 1) {
2828
if (args[0].getValue() instanceof String filePath) {
2929
try {
30-
return Files.readString(Path.of(filePath));
30+
return Files.readString(script.getSecurityManager().getFileSystem().getPath(filePath));
3131
} catch (IOException e) {
3232
throw new ScriptFunctionException(e);
3333
}

core/src/main/java/com/instancify/scriptify/core/script/function/impl/file/ScriptFunctionWriteFile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public Object invoke(Script<?> script, ScriptFunctionArgument[] args) throws Scr
2626
if (args.length == 2) {
2727
if (args[0].getValue() instanceof String filePath && args[1].getValue() instanceof String fileContent) {
2828
try {
29-
return Files.writeString(script.getSecurityManager().getPathAccessor().getAccessiblePath(filePath), fileContent);
29+
return Files.writeString(script.getSecurityManager().getFileSystem().getPath(filePath), fileContent);
3030
} catch (IOException e) {
3131
throw new ScriptFunctionException(e);
3232
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.instancify.scriptify.security;
2+
3+
import com.instancify.scriptify.api.script.security.SecurityFileSystem;
4+
import com.instancify.scriptify.api.script.security.SecurityPathAccessor;
5+
6+
import java.io.File;
7+
import java.nio.file.Path;
8+
9+
public class SecurityFileSystemImpl implements SecurityFileSystem {
10+
11+
private final SecurityPathAccessor pathAccessor;
12+
13+
public SecurityFileSystemImpl(SecurityPathAccessor pathAccessor) {
14+
this.pathAccessor = pathAccessor;
15+
}
16+
17+
@Override
18+
public Path getPath(String path) {
19+
return pathAccessor.getAccessiblePath(path);
20+
}
21+
22+
@Override
23+
public File getFile(String path) {
24+
return this.getPath(path).toFile();
25+
}
26+
27+
@Override
28+
public Path getBasePath() {
29+
return pathAccessor.getBasePath();
30+
}
31+
}

0 commit comments

Comments
 (0)