A Windows path can start with a drive letter and no slash at all. C:dirname is a valid form, and it is the reason CWE-39 exists. The product accepts input that contains a drive letter or Windows volume letter that potentially redirects access to an unintended location or arbitrary file.
If your code runs on Windows, or handles paths that will be interpreted on Windows, a filter that only blocks slashes and dot dot sequences can miss it.
How it happens
A developer builds a path from a base folder and a user supplied name. The check looks for separators and parent directory markers. A name that begins with a drive specifier contains neither, so it passes. The file API then treats the drive letter as the root and the base folder is ignored.
The examples in the record are web and FTP servers from the early 2000s:
- Remote attackers could read arbitrary files by specifying the drive letter in the requested URL (CVE-2001-0038).
- An FTP server allowed attackers to list arbitrary directories using the ls command with a drive letter such as C: (CVE-2001-0255).
- An FTP server allowed a remote attacker to retrieve privileged system information by specifying arbitrary paths (CVE-2001-0687).
- An FTP server allowed listing the contents of arbitrary drives via an ls command that included the drive letter (CVE-2001-0933).
The lesson is not about FTP. It is that a path validator has to know every way the platform can express a root.
// Vulnerable: only checks for separators and ".."
String name = request.getParameter("f");
if (name.contains("/") || name.contains("\\") || name.contains("..")) {
throw new IllegalArgumentException();
}
File f = new File(baseDir, name); // "C:secret.txt" is not caught
What an attacker gains
MITRE lists several outcomes. The attacker may read unexpected files and expose sensitive data. They may modify or overwrite files such as programs, libraries or data, and if the file feeds a security mechanism, bypass it. Overwriting files that get executed can lead to code execution. Deleting or corrupting critical files can crash the product or keep it from restarting.
How to find it
Automated static analysis can follow external input to file operations. On top of that, add drive letter forms to your own tests for any endpoint or function that takes a filename. If your product runs on both Windows and Unix, test on both, since a name that is harmless on one is a root on the other.
How to fix it
Allowlist the characters in a filename. Excluding the colon removes the drive letter form entirely. Then resolve and confirm containment.
// Fixed: strict allowlist, then canonical containment check
if (!name.matches("[A-Za-z0-9_.]{1,64}") || name.indexOf('.') != name.lastIndexOf('.')) {
throw new IllegalArgumentException();
}
Path base = Paths.get(baseDir).toRealPath();
Path target = base.resolve(name).normalize();
if (!target.startsWith(base)) {
throw new IllegalArgumentException();
}
If the data never needs a user chosen name, store files under generated IDs. Run services as an account that cannot reach sensitive drives. The free scan at gold.safeguard.sh/scan can also flag known path handling bugs in your dependencies, no login needed.
Quick check
Why does a slash filter miss C:dirname?
The input has no slash, backslash or dot dot. The drive letter alone changes the root, so a validator that looks only for separators lets it through.
What is the simplest preventive rule?
Allow only a strict character set for filenames, which excludes the colon, and confirm the resolved path stays inside the base directory.