Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refine location checks for PathResource #34167

Closed
stewue opened this issue Dec 27, 2024 · 5 comments
Closed

Refine location checks for PathResource #34167

stewue opened this issue Dec 27, 2024 · 5 comments
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Milestone

Comments

@stewue
Copy link

stewue commented Dec 27, 2024

Hi,

I have currently have a Spring Boot application using Spring Framework 6.1. I tried to upgrade to the newest Spring Boot and Framework version. During upgrading I realized that in my implemented WebMvcConfigurer now an IllegalArgumentException is thrown.

Here a minimal example on how you can reproduce it:

@Configuration
public class MyResourcesConfiguration implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/my/**").addResourceLocations(new PathResource("/demo-directory/"));
    }
}

In the example a Caused by: java.lang.IllegalArgumentException: Resource location does not end with slash: /demo-directory is thrown. The issue is that in 59ec871 an additional check was added in ResourceHandlerUtils. All constructors of PathResource call Path.normalize which removes the passed trailing slash.

I know in this minimal example just ResourceHandlerRegistration.addResourceLocations(String...) can be used. However in reality I'm dynamically adding different resources in a multi module project.

Is this an undesirable side effect of #33815 or how should ResourceHandlerRegistration.addResourceLocations(Resource...) be used with PathResource?

Thank you in advance!

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Dec 27, 2024
@bclozel bclozel added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Dec 29, 2024
@tompson
Copy link

tompson commented Dec 31, 2024

This is also blocking us from upgrading to Spring Framework 6.2

Our config looks like

@Configuration
public class WebMvcConfigurationDev implements WebMvcConfigurer {

	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		registry
				.addResourceHandler("/messages/*")
				.addResourceLocations(new ClassPathResource("/"))
				.resourceChain(false)
				.addResolver(new MessagesResolver())
				.addTransformer(new MessagesTransformer());
	}
}

which we use to resolve message bundles from the classpath.

@bclozel
Copy link
Member

bclozel commented Jan 2, 2025

Thanks for reaching out. I guess we can refine checks for specific resource implementations.

For your case @stewue, the Path API itself will strip the trailing separator so there is no way to enforce it at the resource level. For example, Path path = Paths.get("/static/"); will yield "/static". On the other hand, the createRelative behavior will always result in a nested path element.

PathResource pathResource = new PathResource("/static");
Resource other = pathResource.createRelative("other.txt");
// will yield "/static/other.txt"

So I think that we should generally leave PathResource alone and not attempt to check the resulting path for the location. This should fix your use case.

Now for @tompson 's case, the new ClassPathResource("/") will strip the leading separator as documented:
A leading slash will be removed, as the {@code ClassLoader} resource access methods will not accept it.. So we could ignore the path check if the path is completely empty. This one is a bit tougher to consider since exposing the entire classpath is an application vulnerability in the first place. I get that this should not be a problem in your case because of the custom MessagesResolver/MessagesTransformer, but we should consider this one carefully.

I'll discuss this with the web team and report back here.

@bclozel bclozel self-assigned this Jan 2, 2025
@bclozel bclozel changed the title ResourceHandlerRegistration.addResourceLocations(Resource...) throws IllegalArgumentException with 6.2.x Refine location checks for PathResource Jan 7, 2025
@bclozel
Copy link
Member

bclozel commented Jan 7, 2025

We have discussed this today, here are our conclusions.

We are repurposing this issue to refine the location checks to account for the PathResource behavior. As a result, applications won't get IllegalArgumentException thrown anymore with PathResource.

As for the new ClassPathResource("/") case raised by @tompson , we are aware that there is a specific behavior for root classpath locations (same goes for the JDK actually). But we don't think that we should relax the location check for this case because using a root classpath location is very dangerous in the first place. The application is in danger of exposing the entire classpath to the outside world by doing so. Here, we're advising to relocate the message properties files into a common /messages/ folder and change that to new ClassPathResource("/messages/") instead. We do understand that this is a breaking behavior change but we still think that the security aspect is worth that change.

@bclozel bclozel added this to the 6.2.2 milestone Jan 7, 2025
@bclozel bclozel added type: enhancement A general enhancement for: backport-to-6.1.x Marks an issue as a candidate for backport to 6.1.x and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jan 7, 2025
@github-actions github-actions bot added status: backported An issue that has been backported to maintenance branches and removed for: backport-to-6.1.x Marks an issue as a candidate for backport to 6.1.x labels Jan 8, 2025
@bclozel bclozel closed this as completed in 84be0d8 Jan 8, 2025
@izeye
Copy link
Contributor

izeye commented Jan 10, 2025

The "status: backported" label doesn't seem to be valid as #34213 has been closed as invalid.

@bclozel bclozel removed the status: backported An issue that has been backported to maintenance branches label Jan 10, 2025
@tompson
Copy link

tompson commented Jan 11, 2025

@bclozel ok, thanks for looking into this, we decided to move the files into a /messages subfolder which is better for security anyway

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

5 participants