Description of the false positive
PathNormalizeSanitizer recognizes Path.normalize() and File.getCanonicalPath()/getCanonicalFile(), but not Path.toRealPath().
toRealPath() is strictly stronger than normalize() (resolves .., resolves symlinks, verifies existence). It is the NIO.2 equivalent of getCanonicalPath(). CERT FIO16-J lists them as interchangeable for path traversal prevention.
One-line fix: add "toRealPath" alongside "normalize" in PathNormalizeSanitizer.
Code samples or links to source code
Path base = Paths.get("/safe/dir").toRealPath();
Path resolved = base.resolve(userInput).toRealPath();
if (resolved.startsWith(base + File.separator)) {
// Still flagged as path injection despite toRealPath() normalization
Files.readAllBytes(resolved);
}
The same pattern with .normalize() instead of .toRealPath() is correctly recognized as safe.
Description of the false positive
PathNormalizeSanitizerrecognizesPath.normalize()andFile.getCanonicalPath()/getCanonicalFile(), but notPath.toRealPath().toRealPath()is strictly stronger thannormalize()(resolves.., resolves symlinks, verifies existence). It is the NIO.2 equivalent ofgetCanonicalPath(). CERT FIO16-J lists them as interchangeable for path traversal prevention.One-line fix: add
"toRealPath"alongside"normalize"inPathNormalizeSanitizer.Code samples or links to source code
The same pattern with
.normalize()instead of.toRealPath()is correctly recognized as safe.