I have an API in Spring Boot. In the controller layer, any POST that has a custom object annotated with @RequestBody flags Snyk security findings in the security pipeline.
For example:
public ResponseEntity<CustomObject> getCustomObject(@RequestBody CustomRequest customRequest) {
// code
}
The security report would show:
✗ [Low] Spring Cross-Site Request Forgery (CSRF)
Controller: Line 10
Info: The request parameter is vulnerable to Cross Site Request Forgery (CSRF) attacks due to not using Spring Security. This could allow an attacker to execute requests on a user's behalf. Consider including Spring Security's CSRF protection within your application.
If I remove the @RequestBody, the security report doesn't flag it anymore.
I have tried other validations such as @Valid and @Validated, as well as field value annotations on the object, but nothing works. I am wondering if there is a way around this without having to write a custom deserializer instead of using @RequestBody or adding it as a false positive.
I have an API in Spring Boot. In the controller layer, any POST that has a custom object annotated with @RequestBody flags Snyk security findings in the security pipeline.
For example:
public ResponseEntity<CustomObject> getCustomObject(@RequestBody CustomRequest customRequest) {
// code
}
The security report would show:
✗ [Low] Spring Cross-Site Request Forgery (CSRF)
Controller: Line 10
Info: The request parameter is vulnerable to Cross Site Request Forgery (CSRF) attacks due to not using Spring Security. This could allow an attacker to execute requests on a user's behalf. Consider including Spring Security's CSRF protection within your application.
If I remove the @RequestBody, the security report doesn't flag it anymore.
I have tried other validations such as @Valid and @Validated, as well as field value annotations on the object, but nothing works. I am wondering if there is a way around this without having to write a custom deserializer instead of using @RequestBody or adding it as a false positive.
I have tried other validations such as @Valid and @Validated, as well as field value annotations on the object, but nothing works. I am wondering if there is a way around this without having to write a custom deserializer instead of using @RequestBody or adding it as a false positive.
This has nothing to do with @RequestBody
in particular.
You probably disabled (or didn't configure) CSRF in your security configuration.
If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection
more information about csrf can be found in the official spring security documentation
here is an example of a configuration file taken from the getting started page
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((requests) -> requests
.requestMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
)
.formLogin((form) -> form
.loginPage("/login")
.permitAll()
)
.logout((logout) -> logout.permitAll());
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
If you don't have this in any shape or form, I suggest you start there.