Files
codeql/java/ql/test/query-tests/security/CWE-022/semmle/tests/TaintedPath.java
Owen Mansel-Chan 6057b4b6e9 Fix path sanitizer
2026-07-11 07:28:14 +01:00

131 lines
6.1 KiB
Java

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.nio.file.Path;
import java.nio.file.Paths;
public class TaintedPath {
public void sendUserFile(Socket sock, String user) throws IOException {
BufferedReader filenameReader =
new BufferedReader(new InputStreamReader(sock.getInputStream(), "UTF-8")); // $ Source[java/path-injection]
String filename = filenameReader.readLine();
// BAD: read from a file without checking its path
BufferedReader fileReader = new BufferedReader(new FileReader(filename)); // $ Alert[java/path-injection]
String fileLine = fileReader.readLine();
while (fileLine != null) {
sock.getOutputStream().write(fileLine.getBytes());
fileLine = fileReader.readLine();
}
}
public void sendUserFileGood(Socket sock, String user) throws IOException {
BufferedReader filenameReader =
new BufferedReader(new InputStreamReader(sock.getInputStream(), "UTF-8"));
String filename = filenameReader.readLine();
// GOOD: ensure that the file is in a designated folder in the user's home directory
if (!filename.contains("..") && filename.startsWith("/home/" + user + "/public/")) {
BufferedReader fileReader = new BufferedReader(new FileReader(filename));
String fileLine = fileReader.readLine();
while (fileLine != null) {
sock.getOutputStream().write(fileLine.getBytes());
fileLine = fileReader.readLine();
}
}
}
public void sendUserFileGood2(Socket sock, String user) throws Exception {
BufferedReader filenameReader =
new BufferedReader(new InputStreamReader(sock.getInputStream(), "UTF-8"));
String filename = filenameReader.readLine();
Path publicFolder = Paths.get("/home/" + user + "/public").normalize().toAbsolutePath();
Path filePath = publicFolder.resolve(filename).normalize().toAbsolutePath();
// GOOD: ensure that the path stays within the public folder
if (!filePath.startsWith(publicFolder + File.separator)) {
throw new IllegalArgumentException("Invalid filename");
}
BufferedReader fileReader = new BufferedReader(new FileReader(filePath.toString()));
String fileLine = fileReader.readLine();
while (fileLine != null) {
sock.getOutputStream().write(fileLine.getBytes());
fileLine = fileReader.readLine();
}
}
public void sendUserFileGood3(Socket sock, String user) throws Exception {
BufferedReader filenameReader =
new BufferedReader(new InputStreamReader(sock.getInputStream(), "UTF-8"));
String filename = filenameReader.readLine();
// GOOD: ensure that the filename has no path separators or parent directory references
if (filename.contains("..") || filename.contains("/") || filename.contains("\\")) {
throw new IllegalArgumentException("Invalid filename");
}
BufferedReader fileReader = new BufferedReader(new FileReader(filename));
String fileLine = fileReader.readLine();
while (fileLine != null) {
sock.getOutputStream().write(fileLine.getBytes());
fileLine = fileReader.readLine();
}
}
public void sendUserFileGood5(Socket sock, String user) throws Exception {
BufferedReader filenameReader =
new BufferedReader(new InputStreamReader(sock.getInputStream(), "UTF-8"));
String filename = filenameReader.readLine();
Path publicFolder = Paths.get("/home/" + user + "/public").toRealPath();
Path filePath = publicFolder.resolve(filename).toRealPath();
// GOOD: toRealPath() normalizes the path (resolves ".." and symlinks),
// equivalent to File.getCanonicalPath()
if (!filePath.startsWith(publicFolder + File.separator)) {
throw new IllegalArgumentException("Invalid filename");
}
BufferedReader fileReader = new BufferedReader(new FileReader(filePath.toString()));
String fileLine = fileReader.readLine();
while (fileLine != null) {
sock.getOutputStream().write(fileLine.getBytes());
fileLine = fileReader.readLine();
}
}
public void sendUserFileBad2(Socket sock, String user) throws IOException {
BufferedReader filenameReader =
new BufferedReader(new InputStreamReader(sock.getInputStream(), "UTF-8")); // $ Source[java/path-injection]
String filename = filenameReader.readLine();
File file = new File(filename);
String baseName = file.getName();
// BAD: `getName()` strips directory separators but does not remove a `..`
// component (`new File("..").getName()` returns ".."), so it is not a
// complete path injection sanitizer.
BufferedReader fileReader = new BufferedReader(new FileReader(baseName)); // $ Alert[java/path-injection]
String fileLine = fileReader.readLine();
while (fileLine != null) {
sock.getOutputStream().write(fileLine.getBytes());
fileLine = fileReader.readLine();
}
}
public void sendUserFileGood4(Socket sock, String user) throws IOException {
BufferedReader filenameReader =
new BufferedReader(new InputStreamReader(sock.getInputStream(), "UTF-8"));
String filename = filenameReader.readLine();
File file = new File(filename);
String baseName = file.getName();
// GOOD: `getName()` strips directory separators and the `..` check removes
// the only remaining traversal possibility.
if (!baseName.contains("..")) {
BufferedReader fileReader = new BufferedReader(new FileReader(baseName));
String fileLine = fileReader.readLine();
while (fileLine != null) {
sock.getOutputStream().write(fileLine.getBytes());
fileLine = fileReader.readLine();
}
}
}
}