Java CWE-73 file path cleanser implementation requirements
For CWE-73, Veracode Static Analysis supports a Java file path cleanser pattern that validates an untrusted file name against an allowed base directory and returns a validated file object.
This guidance is separate from custom cleanser annotations, which support mitigation handling for findings.
A file path cleanser must validate that a serialized file path resolves to a file inside an explicitly allowed base directory. If validation succeeds, the cleanser returns a validated file object that subsequent code can use for file operations.
A valid file path cleanser does not make the returned file object safe for every possible use. The returned object is considered mitigated only for CWE-73 findings. Veracode Static Analysis can still report other flaw types or unsafe API usage.
Required method structure
A Java file path cleanser must accept two parameters and return a validated file reference.
validate(basePath, unsafeFilename) -> validatedFile
The method name, parameter names, and return value name are not significant. However, the implementation must follow this structure:
- The first argument is the allowed base directory.
- The second argument is the untrusted file name or relative path.
- The return value is a validated
java.io.Fileorjava.nio.file.Pathobject.
The return value must not be a serialized representation of the validated file name, such as a String. The method must return a validated object reference that the application can use for subsequent file operations.
The following sections describe each part of this structure.
validate()
The validate() method determines whether a serialized file name is valid for use under an allowed base directory.
If the path is valid, the method returns a validated file object. If the path resolves outside the allowed base directory, the method must fail securely, such as by throwing a security exception.
This method mitigates only CWE-73. It does not suppress findings for other flaw classes.
basePath
The first argument to the cleanser is basePath. This value identifies the allowed directory that the application can read from or write to.
Although the developer defines this value, Veracode Static Analysis still validates how the basePath value is created. The basePath value must not come from untrusted input or from inherently unsafe sources.
Examples:
| Input source | Security posture |
|---|---|
| HTTP query parameter name or value | Unsafe |
| HTTP header or cookie | Unsafe |
| POST, PUT, or PATCH request body | Unsafe |
| WebSocket message | Unsafe |
| Hard-coded string literal at the call site | Safe |
| Statically defined constant | Safe |
| Environment variable in a web application scan | Safe |
| Environment variable in a non-web-application scan | Unsafe |
If basePath is concatenated with untrusted data or set directly from untrusted data, Veracode Static Analysis does not consider the cleanser valid, and the cleanser does not affect CWE-73 flaw behavior.
unsafeFilename
The second argument to the cleanser is unsafeFilename. This value contains untrusted data in the form of a serialized file path.
This value is typically a relative path or a file name. However, malicious input might include path traversal sequences or absolute path syntax that resolves to a directory outside the allowed basePath.
When the cleanser is implemented correctly, any path that resolves outside the allowed base directory must fail validation.
validatedFile
The output of the cleanser is a reference to the validated file. Supported return types are java.io.File and java.nio.file.Path.
The validated file object is considered mitigated for CWE-73 findings. Subsequent read or write operations that use this validated object are also considered mitigated for CWE-73.
This mitigation does not apply to other flaw types. Veracode Static Analysis can still report other applicable findings.
Choosing between File and Path
Choose the implementation style based on how you want the cleanser to handle file names that start with / when resolved against basePath.
With the File API, a child path that starts with / is treated as relative to the parent File.
With the Path API, resolving a path that starts with / treats the child path as absolute. In most secure implementations, this causes validation to fail because the resolved path is outside the allowed base directory.
Example:
File API:
basePath = /path/to/app/tmp
unsafeFilename = /etc/passwd
result = /path/to/app/tmp/etc/passwd
Path API:
basePath = /path/to/app/tmp
unsafeFilename = /etc/passwd
result = /etc/passwd
Do not use / as the allowed basePath. Using / effectively allows the entire file system and makes the validation meaningless.
Example implementation
The following example shows cleanser methods for both java.io.File and java.nio.file.Path.
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
public class Cleansers {
public static File validateFile(String basePath, String unsafeFilename) throws IOException {
File parent = new File(basePath);
String safeDestination = parent.getCanonicalPath();
File fileBeingValidated = new File(parent, unsafeFilename);
String canonicalPath = fileBeingValidated.getCanonicalPath();
if (canonicalPath.startsWith(safeDestination)) {
return fileBeingValidated;
}
throw new SecurityException("Security incident - path traversal attempt!");
}
public static Path validatePath(String basePath, String unsafeFilename) {
Path parent = Path.of(basePath);
Path safeDestination = parent.toAbsolutePath().normalize();
Path pathBeingValidated = parent.resolve(unsafeFilename);
Path canonicalPath = pathBeingValidated.toAbsolutePath().normalize();
if (canonicalPath.startsWith(safeDestination)) {
return pathBeingValidated;
}
throw new SecurityException("Security incident - path traversal attempt!");
}
}
The example omits a package declaration so that you can copy it into your own package structure.
Example usage
Use the returned validated object for subsequent file operations.
File validatedFile = Cleansers.validateFile("/path/to/app/tmp", userProvidedFilename);
Or:
Path validatedPath = Cleansers.validatePath("/path/to/app/tmp", userProvidedFilename);
Do not discard the returned validated object and reconstruct a new file path from the original untrusted input.
Summary of requirements
To be accepted as a valid CWE-73 file path cleanser pattern:
- The method must accept both the allowed base path and the untrusted file name.
- The allowed base path must not be derived from untrusted input.
- The method must validate the fully resolved path against the allowed base directory.
- The method must return a validated
FileorPathobject. - The calling code must use the returned validated object.
- All data paths to the file operation must pass through the cleanser.
- The cleanser mitigates only CWE-73 and does not suppress unrelated flaw types.