VNX-JAVA-010 – Spring CSRF Protection Disabled
Overview
This rule detects Spring Security configuration code that explicitly disables CSRF (Cross-Site Request Forgery) protection through any of the supported API forms: csrf().disable(), csrf(csrf -> csrf.disable()), csrf(AbstractHttpConfigurer::disable), .csrf().ignoringAntMatchers(...), or the shorthand csrf.disable(). Disabling CSRF protection removes the token check that prevents malicious websites from submitting state-changing requests on behalf of authenticated users. This is CWE-352.
Severity: Medium | CWE: CWE-352 – Cross-Site Request Forgery (CSRF)
Why This Matters
A CSRF attack works by inducing an authenticated user’s browser to send a request to your application. Because browsers automatically include cookies with cross-origin requests, a session cookie present in the browser is sent along with the forged request. Without a CSRF token — a unique, unpredictable value tied to the user’s session that a cross-origin attacker cannot read — your server has no way to distinguish a legitimate form submission from a forged one.
Practical consequences include account takeover (an attacker can change a victim’s email address or password), financial fraud (trigger a funds transfer or purchase), privilege escalation (promote an account to admin), and data destruction (delete records). CSRF is particularly dangerous in banking applications, admin dashboards, and SaaS tools where authenticated actions have high business impact.
csrf().disable() is commonly added during development to simplify API testing with curl or Postman, and is sometimes cargo-culted into stateless REST APIs on the assumption that they are not vulnerable. Stateless APIs that use cookie-based session authentication are vulnerable. Stateless APIs using Authorization: Bearer headers with JWTs are generally safe, as browsers do not automatically attach custom headers to cross-origin requests — but the Spring configuration should reflect the actual authentication mechanism.
What Gets Flagged
Any .java file containing one of the CSRF disable patterns.
// FLAGGED: legacy Spring Security API
http.csrf().disable();
// FLAGGED: lambda DSL form
http.csrf(csrf -> csrf.disable());
// FLAGGED: method reference form
http.csrf(AbstractHttpConfigurer::disable);
// FLAGGED: partially disabled (still creates a vulnerability surface)
http.csrf().ignoringAntMatchers("/api/**");
Remediation
Remove the
csrf().disable()call entirely. Spring Security enables CSRF protection by default. Simply removing the disable call restores it. For form-based authentication, use Spring’sCsrfTokenRepository(defaulting toHttpSessionCsrfTokenRepository) and include the_csrftoken in all HTML forms using Thymeleaf’sth:action, JSP’s<sec:csrfInput/>, or a hidden field populated from the session.// SAFE: CSRF enabled (default) with explicit repository configuration @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .formLogin(Customizer.withDefaults()) .csrf(csrf -> csrf .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) ); return http.build(); }For SPAs and AJAX-heavy applications, use
CookieCsrfTokenRepository. This stores the CSRF token in a cookie readable by JavaScript (XSRF-TOKEN) while requiring it to be echoed back as an HTTP header (X-XSRF-TOKEN). Angular’sHttpClientand Axios both support this pattern out of the box.// SAFE: cookie-based CSRF token for Angular/React SPA http.csrf(csrf -> csrf .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()) );// Angular reads XSRF-TOKEN cookie and sends X-XSRF-TOKEN header automatically // No additional configuration needed in Angular's HttpClientModuleFor pure stateless REST APIs using Bearer token authentication, explicitly document the decision. If your API genuinely authenticates solely via
Authorization: Bearerheaders (not cookies), CSRF is not applicable. Leave a clear code comment explaining this rather than simply callingdisable()without context:// SAFE: stateless JWT API — CSRF not applicable because no cookie authentication is used http .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .csrf(csrf -> csrf.disable()) // safe: bearer token auth only, no session cookies .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));Add integration tests that verify CSRF protection is active. Use Spring’s
MockMvcwithSecurityMockMvcRequestPostProcessors.csrf()removed to assert that POST endpoints return 403 without a valid token.