Recipe Name:
Session management: Avoid CSRF: Use narrow mapping for state-changing methods
Description:
Non-specified RequestMapping method will map to any HTTP request
Level:
error
Language:
- java
Tags:
- Spring
- security
- framework specific
- web
- Spring Web
- CSRF
Documentation
Secure coding practices prescribe that state-changing methods should be annoted with narrowed mapping to the HTTP request methods POST, PUT, DELETE, or PATCH.
Methods annotated with RequestMapping
are by default mapped to all the HTTP request methods. However, Spring Security's CSRF protection is not enabled by default for the HTTP request methods GET, HEAD, TRACE, and OPTIONS, as this could cause the tokens to be leaked. Therefore, it is advised to annotate state-changing methods with more narrowing mappings to the HTTP methods POSt, PUT, DELETE, or PATCH.
Class information:
package org.springframework.web.bind.annotation PostMapping GetMapping PutMapping DeleteMapping PatchMappingCorrect code example:
@Controller public class SafeController { /** * For methods without side-effects use @GetMapping. */ @GetMapping("/path") public String readData() { // No state-changing operations performed within this method. return ""; } /** * For state-changing methods use either @PostMapping, @PutMapping, @DeleteMapping, or @PatchMapping. */ @PostMapping("/path") public void writeData() { // State-changing operations performed within this method. } }
Recipe
id: scw:spring:web:csrf:state-changing-methods-mapping version: 10 metadata: name: 'Session management: Avoid CSRF: Use narrow mapping for state-changing methods' shortDescription: Non-specified RequestMapping method will map to any HTTP request level: error language: java newCodeOnly: false scwCategory: session:csrf enabled: true descriptionFile: descriptions/SessionmanagementAvoidCSRFUsenarrowmappingforstate-changingmethods.html tags: Spring;security;framework specific;web;Spring Web;CSRF search: annotation: owner: method: {} not: parameters: - name: method in: typeDeclaration: with: annotation: type: org.springframework.stereotype.Controller type: org.springframework.web.bind.annotation.RequestMapping availableFixes: - name: Set to @GetMapping actions: - rewrite: to: '@org.springframework.web.bind.annotation.GetMapping({{{ elementValuePairs }}})' - name: Set to @PostMapping actions: - rewrite: to: '@org.springframework.web.bind.annotation.PostMapping({{{ elementValuePairs }}})' - name: Set to @PutMapping actions: - rewrite: to: '@org.springframework.web.bind.annotation.PutMapping({{{ elementValuePairs }}})' - name: Set to @DeleteMapping actions: - rewrite: to: '@org.springframework.web.bind.annotation.DeleteMapping({{{ elementValuePairs }}})' - name: Set to @PatchMapping actions: - rewrite: to: '@org.springframework.web.bind.annotation.PatchMapping({{{ elementValuePairs }}})' - name: Set to HEAD by adding method parameter actions: - rewrite: to: '@RequestMapping(method = org.springframework.web.bind.annotation.RequestMethod.HEAD)' - name: Set to OPTIONS by adding method parameter actions: - rewrite: to: '@RequestMapping(method = org.springframework.web.bind.annotation.RequestMethod.OPTIONS)' - name: Set to TRACE by adding method parameter actions: - rewrite: to: '@RequestMapping(method = org.springframework.web.bind.annotation.RequestMethod.TRACE)'