spring-projects / spring-projects/spring-security

`PreAuthorise` throws AuthenticationCredentialsNotFoundException when a UUID finishes with a space.

Open
#16,626 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage type: bug
Dominant language
Java
Stars
9.6k
Forks
6.3k
Avg merge
2d 11h
Merged PRs (30d)
52

Description

Describe the bug
A path variable which has type UUID and is referenced in hasPermission will throw an AuthenticationCredentialsNotFoundException when it has a space (%20) at the start or end of a valid UUID. Instead of being treated as an invalid UUID.

This occurs regardless of if the user is authenticated correctly or not.

To Reproduce
Steps to reproduce the behavior.

  1. have a simple request handler that uses hasPermission referencing a path variable that is a UUID.
    @RequestMapping(path = ["/property/{id}/todo/"], method = [GET])
    @PreAuthorize("hasPermission($id, 'MyCheck')")
    fun getUpcomingForProperty(@PathVariable id: UUID): TodoDto = TodoDto() // method logic appears to be irrelevant
  1. Call the URL with %20 after the end of a valid UUID e.g. property/8ceaa391-954b-45d3-a8c4-de81a12fc2db%20/todo/
  2. An exception is returned:
Request failed internally: An Authentication object was not found in the SecurityContext. Trigger point: <generated>:-1. Caused by: AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
	at upside.controllers.TaskController$$SpringCGLIB$$0.getUpcomingForProperty(<generated>)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:527)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614)
	at nct.core.security.InternalAuthFilter.doFilterInternal(InternalAuthFilter.kt:35)
	at upside.filters.AccessLoggingFilter.doFilterWrapped(AccessLoggingFilter.java:70)
	at upside.filters.AccessLoggingFilter.doFilterInternal(AccessLoggingFilter.java:63)
	at upside.filters.GCPLoggingAwareFilter.doFilterInternal(GCPLoggingAwareFilter.kt:19)
	at nct.core.ObjectifyJakartaFilter.doFilter(ObjectifyJakartaFilter.kt:18)

Note that this only occurs if the character is something that String.trim() removes, if the character is at the end or start of the URL. It does not occur if the space is anywhere else in the UUID or for other special characters such as - or ..

Expected behavior

It should return a 400 error (behave the same way as any other invalid UUID value does in that part of the path).
However treating it as a valid UUID ignoring the space would also be acceptable.

Sample

    @RequestMapping(path = ["/property/{id}/todo/"], method = [GET])
    @PreAuthorize("hasPermission($id, 'MyCheck')")
    fun getUpcomingForProperty(@PathVariable id: UUID): TodoDto = TodoDto() // method logic appears to be irrelevant

If needed I can probably create a proper sample on Monday.

Reports that include a sample will take priority over reports that do not.
At times, we may require a sample, so it is good to try and include a sample up front.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the Kotlin handler using @PathVariable UUID and @PreAuthorize("hasPermission") with a trailing %20, then trace whether UUID conversion or permission evaluation handles the trimmed value. Done means the request consistently returns a 400 for an invalid UUID rather than AuthenticationCredentialsNotFoundException, with a regression test covering the path-variable case.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, kotlin, spring
Domain
authentication, backend, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.