Skip to content

CSRF form validation should fall back to servlet request parameters when JAX-RS form-body access is unreliable #403

@robertpatrick

Description

@robertpatrick

Problem

Krazo CSRF validation currently checks the CSRF header first and then falls back to reading the submitted form body through FormEntityProvider. On some servlet/JAX-RS integrations, the submitted form parameters are already parsed and available through HttpServletRequest, but the JAX-RS form-body path is no longer reliable because the body has already been consumed.

This causes valid CSRF-protected form submissions to fail with 403, even though the submitted _csrf form field is present and correct.

Observed Behavior

On WebLogic with Jersey-based MVC/TCK execution:

  • Krazo receives a valid CSRF-protected form POST.
  • HttpServletRequest#getParameterMap() contains _csrf.
  • Jersey logs that the request body has already been consumed.
  • Krazo falls through to its form-body validation path and rejects the request with 403.

Expected Behavior

If the CSRF header is absent, Krazo should also accept a valid token from HttpServletRequest.getParameter(token.getParamName()) before depending on re-parsing the JAX-RS entity body.

Why This Belongs In Krazo

This is not a container authorization/role-mapping issue. It is a CSRF validation interoperability issue between servlet request parameter parsing and JAX-RS entity handling. Krazo already owns the CSRF validation flow, so the fallback should live in CsrfValidateFilter.

Reproducer / Evidence

A targeted MVC TCK probe showed:

  • With the existing WebLogic runner workaround disabled, valid form submission failed with 403.
  • Server diagnostics showed _csrf was present in the servlet request parameters.
  • After adding a servlet-request fallback in CsrfValidateFilter, the same test passed.

Relevant TCK slice:

  • ee.jakarta.tck.mvc.tests.security.csrf.header.CsrfDefaultHeaderTest
  • After the fix: Tests run: 4, Failures: 0, Errors: 0, Skipped: 0

Proposed Fix

In CsrfValidateFilter:

  1. Check the CSRF header first, as today.
  2. If the header is absent, check HttpServletRequest.getParameter(token.getParamName()).
  3. Only if that also fails, fall back to the existing JAX-RS form-body parsing path.

Test Coverage

Add a unit test covering the servlet-request fallback path so valid CSRF form submissions do not regress when the JAX-RS entity stream is not the reliable source of form parameters.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions