Search code examples
spring-bootfavicon

How To Set Strict-Transport-Security Header for /favicon.ico in Spring Boot


My Spring Boot application (v1.4.2, with undertow starter) is currently setting the Strict-Transport-Security header for every resource it serves up, including API resources from my spring-web RestControllers, and static resources in /src/main/resources/static. The only exception I've found is /favicon.ico. The missing header on this file is triggering findings in our security scans and I'd like to clear them up.

Here's what I've tried so far:

  1. Disabled Spring's custom favicon handling with spring.mvc.favicon.enabled=false
  2. Added explicit header handling for all resources in HttpSecurity configuration:

    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) {
            http.headers()
                .httpStrictTransportSecurity()
                .requestMatcher(request -> true);
        }
    }
    

It seems no matter what I do, this resource produces a different set of HTTP response headers than every other resource served up by Spring Boot. For instance, the cache control headers that are applied to all my other responses are absent from /favicon.ico.

Interestingly, I've found that the one header I am able to affect for this file is the Content-Type header (default behavior returns Content-Type: application/octet-stream) by adding a MimeMapping to a EmbeddedServletContainerCustomizer:

@Configuration
public class WebConfigurer implements EmbeddedServletContainerCustomizer {

    @Override
    public void customize(ConfigurableEmbeddedServletContainer container) {
        MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);
        mappings.add("ico", "image/x-icon");
        container.setMimeMappings(mappings);
    }
}

Solution

  • SpringBootWebSecurityConfiguration has a default list of ignored paths that are added to one of the first security filters in the servlet stack:

    private static List<String> DEFAULT_IGNORED = Arrays.asList(
        "/css/**", 
        "/js/**",
        "/images/**", 
        "/webjars/**", 
        "/**/favicon.ico");
    

    You can override this list of ignored paths by setting the "ignored" list on a SecurityProperties bean.

    @Bean
    public SecurityProperties securityProperties() {
        SecurityProperties props = new SecurityProperties();
        props.setIgnored(Arrays.asList("none"));
        return props;
    }
    

    Passing a null or empty list into setIgnored() produces the default behavior, so I've added the keyword "none" to indicate I want no paths to be ignored. SpringBootWebSecurityConfiguration removes "none" from the list before building the "ignores" filter.