spring-security icon indicating copy to clipboard operation
spring-security copied to clipboard

SecurityContextHolderThreadLocalAccessor should not share SecurityContext instance across threads

Open ttddyy opened this issue 1 month ago • 0 comments

We encountered an issue where authentication was being mixed across threads. During our analysis, we discovered that SecurityContextHolderThreadLocalAccessor propagates the same SecurityContext to other threads when using Micrometer Context Propagation.

Below is a simplified example that demonstrates the problem:

Authentication authA = ...
Authentication authB = ...

// Set authA in the main thread
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(authA);

Runnable runnable = () -> {
    // This retrieves the *same* SecurityContext instance as the main thread
    SecurityContext context = SecurityContextHolder.getContext();
    context.setAuthentication(authB);
};

// Executor integrated with Micrometer Context Propagation
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setTaskDecorator(new ContextPropagatingTaskDecorator());
executor.afterPropertiesSet();

executor.execute(runnable);

// Wait until runnable finishes
...

// Authentication has now changed unexpectedly
SecurityContext current = SecurityContextHolder.getContext();
current.getAuthentication();  // returns authB instead of authA

When Micrometer context propagation is in use, the current implementation effectively shares the SecurityContext instance between threads. This is generally not recommended and can cause subtle and hard-to-diagnose behavior, such as authentication leakage across threads.

We understand that swapping the Authentication directly is rarely a good practice. However, if a new SecurityContext had been used for the different thread, it would have been isolated and harmless. The underlying issue happens only because the same SecurityContext instance is shared across threads.

Proposed Change

This PR updates SecurityContextHolderThreadLocalAccessor to create a new SecurityContext whenever a thread switch happens, and propagte only the Authentication.

I have targetted the PR to 6.5.x branch as I consider it is a bug and should be fixed in there and up.

ttddyy avatar Nov 23 '25 06:11 ttddyy