fix #97: normalize file locator paths and add optional base-directory confinement - #123
Open
phaneendra-injarapu wants to merge 1 commit into
Open
Conversation
…rectory confinement FileLocatorStrategy passed the location specification directly to into the MessageHolder output, and there was no way to keep resolution inside an intended directory when the specification came from an untrusted source. Normalize the specification through java.nio.file.Path before it becomes a File, and report an invalid path through the MessageHolder like every other failure in this class instead of throwing. Add a FileLocatorStrategy(File baseDirectory) constructor for callers that handle untrusted specifications. It resolves relative specifications against the base directory and refuses anything resolving outside it, comparing canonical paths so a symbolic link pointing out of the base directory is also refused. The out-of-base check runs before the existence check so a refused path does not reveal whether the file exists. The no-arg constructor keeps its previous semantics, so existing callers are unaffected.
elharo
requested changes
Aug 5, 2026
| /** | ||
| * file locator strategy. | ||
| * | ||
| * <p> |
Contributor
There was a problem hiding this comment.
write this by hand. This should describe the class, not the bug.
| /** | ||
| * Create a strategy that only resolves files in the given base directory. | ||
| * | ||
| * @param baseDirectory the directory that contains the files to resolve; a relative specification is resolved |
| } | ||
|
|
||
| if (baseDirectory != null && !isInBaseDirectory(file)) { | ||
| messageHolder.addMessage( |
Contributor
There was a problem hiding this comment.
why not just throw an exception here?
| } catch (InvalidPathException e) { | ||
| messageHolder.addMessage("File: " + locationSpecification + " is not a valid path."); | ||
|
|
||
| return null; |
Contributor
There was a problem hiding this comment.
This null return needs to be well documented, if it's done at all. Am=n exception feels more appropriate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #97 (originally reported as bug #15).
Problem
FileLocatorStrategy.resolvepassed the location specification straight tonew File(locationSpecification)with no normalization and no boundary check.Two consequences:
..and.elements survived into the resolvedFile, so theFilehandedback to callers (and the path printed into the
MessageHolder) did not matchthe file actually being addressed.
specification from an untrusted source had no way to keep resolution inside an
intended directory —
../../etc/passwdresolved happily.As the issue notes, this is low priority in the normal Maven plugin case, where
the POM supplying the specification is trusted. The fix is therefore scoped to
close the gap without changing behaviour for existing callers.
How
1. Normalization, always on. The specification is parsed as a
Pathandnormalize()d before it becomes aFile, so..and.elements are collapsedlexically. A specification that is not a valid path (for example one containing a
NUL byte) now adds a message and returns
null, which is how this class alreadyreports every other failure, instead of throwing
InvalidPathExceptionat thecaller.
2. Optional confinement, opt-in. Normalization alone cannot stop traversal
here: with no root to compare against, an absolute or upward-pointing path is a
perfectly legitimate request for this strategy, and rejecting it would break
existing users. So the boundary is introduced as a new constructor:
The two pre-existing tests are unchanged and still pass.
Contribution Checklist
(6 new tests in
FileLocatorStrategyTest.shouldNormalizeTraversalSequencesInTheSpecificationfails against the previousimplementation, which returned an un-normalized
File. The four base-directory testsexercise the
FileLocatorStrategy(File)constructor this PR introduces, so they cannotcompile against the previous implementation at all.
shouldRejectNullSpecificationpinsdown behaviour that was previously incidental — the old code also threw NPE, from
new File(null).)mvn verifyto make sure basic checks pass.(Test suite verified: 0 failures. Main sources compile at
--release 8.mvn checkstyle:checkreports 0 Checkstyle violations, and spotless and apache-rat areclean. A full
mvn verifycould not be completed locally because the environment has noaccess to Maven Central to resolve the surefire plugin's dependencies; relying on CI for
the complete run.)