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.