Skip to content

Path traversal via bundle descriptor resource names (CWE-22) #265

Description

@elharo

Summary

AbstractProcessRemoteResourcesMojo.processResourceBundles() builds the output file path directly from a remote bundle descriptor entry and writes into it without validating or normalizing the name:

File outputFile = new File(outputDirectory, projectResource);
FileUtils.mkdir(outputFile.getParentFile().getAbsolutePath());
...
URL bundleResourceUrl = classLoader.getResource(bundleResource);
if (bundleResourceUrl != null) {
    FileUtils.copyURLToFile(bundleResourceUrl, outputFile);
}

src/main/java/org/apache/maven/plugin/resources/remote/AbstractProcessRemoteResourcesMojo.java:936-963

Problems

  1. new File(parent, child) silently ignores parent when child is absolute, so an absolute <remoteResource>/etc/...</remoteResource> in the descriptor targets an arbitrary path.
  2. .. segments in the descriptor entry escape the output directory.

Impact

Content writes are partially constrained: non-.vm resources are only copied when classLoader.getResource(name) resolves the same (traversal) name, which usually fails. However:

  • FileUtils.mkdir(outputFile.getParentFile()...) runs unconditionally before that check (:938), so an untrusted bundle can create directories anywhere the build user can write.
  • The local-override copy path copyResourceIfExists() (:614-664) writes local project files to the traversal-resolved target, so a file outside the output directory can be overwritten when the layout lines up.
  • The .vm path uses the same unsanitized name for velocity.mergeTemplate(...).

A malicious/third-party bundle can create arbitrary directories (and, in the override case, overwrite files) outside the configured output directory.

Suggested fix

Validate/denormalize resource names before use: reject names containing .., leading /, backslashes, or drive letters; or resolve new File(outputDirectory, name) and verify it stays inside outputDirectory before mkdir/copy.

Note

See also copyProjectRootIfExists() (:666-679) and copyResourceIfExists() (:614-664) which use the same unsanitized bundleResourceName/projectResource to derive source files.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions