VYPR
Medium severity6.3NVD Advisory· Published Apr 26, 2026· Updated Apr 27, 2026

CVE-2026-7045

CVE-2026-7045

Description

A vulnerability was determined in baomidou dynamic-datasource 2.5.0. Affected by this vulnerability is the function DsSpelExpressionProcessor#doDetermineDatasource of the file dynamic-datasource-spring/src/main/java/com/baomidou/dynamic/datasource/processor/DsSpelExpressionProcessor.java of the component StandardEvaluationContext/SpelExpressionParser. This manipulation causes injection. The attack may be initiated remotely. Patch name: 273fcedaee984c08197c0890f14190b86ab7e0b8. It is recommended to apply a patch to fix this issue.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
com.baomidou:dynamic-datasource-springMaven
<= 4.5.0

Affected products

1

Patches

1
273fcedaee98

Fix SpEL injection (potential RCE) in DsSpelExpressionProcessor (#767)

6 files changed · +132 0
  • dynamic-datasource-spring-boot3-starter/src/main/java/com/baomidou/dynamic/datasource/spring/boot/autoconfigure/DynamicDataSourceAopConfiguration.java+1 0 modified
    @@ -66,6 +66,7 @@ public DsProcessor dsProcessor(BeanFactory beanFactory) {
             DsProcessor sessionProcessor = new DsJakartaSessionProcessor();
             DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor();
             spelExpressionProcessor.setBeanResolver(new BeanFactoryResolver(beanFactory));
    +        spelExpressionProcessor.setAllowedSpelTypeAccess(properties.getAop().getAllowedSpelTypeAccess());
             headerProcessor.setNextProcessor(sessionProcessor);
             sessionProcessor.setNextProcessor(spelExpressionProcessor);
             return headerProcessor;
    
  • dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/common/v3/DsSpelExpressionProcessorSecurityTest.java+89 0 added
    @@ -0,0 +1,89 @@
    +/*
    + * Copyright © 2018 organization baomidou
    + *
    + * Licensed under the Apache License, Version 2.0 (the "License");
    + * you may not use this file except in compliance with the License.
    + * You may obtain a copy of the License at
    + *
    + *     http://www.apache.org/licenses/LICENSE-2.0
    + *
    + * Unless required by applicable law or agreed to in writing, software
    + * distributed under the License is distributed on an "AS IS" BASIS,
    + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    + * See the License for the specific language governing permissions and
    + * limitations under the License.
    + */
    +package com.baomidou.dynamic.datasource.common.v3;
    +
    +import com.baomidou.dynamic.datasource.processor.DsSpelExpressionProcessor;
    +import org.aopalliance.intercept.MethodInvocation;
    +import org.junit.jupiter.api.BeforeEach;
    +import org.junit.jupiter.api.Test;
    +import org.springframework.expression.EvaluationException;
    +
    +import java.lang.reflect.Method;
    +
    +import static org.junit.jupiter.api.Assertions.assertEquals;
    +import static org.junit.jupiter.api.Assertions.assertThrows;
    +import static org.mockito.Mockito.mock;
    +import static org.mockito.Mockito.when;
    +
    +/**
    + * Security tests for {@link DsSpelExpressionProcessor} verifying that SpEL injection via
    + * type references (T(...)) is blocked to prevent Remote Code Execution, and that the
    + * behaviour can be restored by explicitly enabling {@code allowedSpelTypeAccess}.
    + */
    +class DsSpelExpressionProcessorSecurityTest {
    +
    +    private DsSpelExpressionProcessor processor;
    +    private MethodInvocation invocation;
    +
    +    @BeforeEach
    +    void setUp() throws Exception {
    +        processor = new DsSpelExpressionProcessor();
    +
    +        Method method = SampleService.class.getMethod("getByTenant", String.class);
    +        invocation = mock(MethodInvocation.class);
    +        when(invocation.getMethod()).thenReturn(method);
    +        when(invocation.getArguments()).thenReturn(new Object[]{"tenant1"});
    +        when(invocation.getThis()).thenReturn(new SampleService());
    +    }
    +
    +    @Test
    +    void normalSpelExpressionShouldWork() {
    +        // #tenant reads the method parameter value normally
    +        String result = processor.doDetermineDatasource(invocation, "#tenant");
    +        assertEquals("tenant1", result);
    +    }
    +
    +    @Test
    +    void typeReferenceExpressionShouldBeBlockedByDefault() {
    +        // T(...) type references must be blocked to prevent SpEL injection / RCE
    +        assertThrows(EvaluationException.class, () ->
    +                processor.doDetermineDatasource(invocation, "T(java.lang.Runtime).getRuntime().exec('id')")
    +        );
    +    }
    +
    +    @Test
    +    void newInstanceExpressionShouldBeBlockedByDefault() {
    +        // new Type(...) constructor invocations must also be blocked
    +        assertThrows(EvaluationException.class, () ->
    +                processor.doDetermineDatasource(invocation, "new java.lang.ProcessBuilder('id').start()")
    +        );
    +    }
    +
    +    @Test
    +    void typeReferenceExpressionShouldWorkWhenExplicitlyAllowed() {
    +        // When allowedSpelTypeAccess=true, T(...) expressions are permitted (opt-in unsafe mode)
    +        processor.setAllowedSpelTypeAccess(true);
    +        // T(java.lang.String) is a safe type reference to verify the restriction is lifted
    +        String result = processor.doDetermineDatasource(invocation, "T(java.lang.String).valueOf(#tenant)");
    +        assertEquals("tenant1", result);
    +    }
    +
    +    static class SampleService {
    +        public String getByTenant(String tenant) {
    +            return tenant;
    +        }
    +    }
    +}
    
  • dynamic-datasource-spring-boot4-starter/src/main/java/com/baomidou/dynamic/datasource/spring/boot/autoconfigure/DynamicDataSourceAopConfiguration.java+1 0 modified
    @@ -66,6 +66,7 @@ public DsProcessor dsProcessor(BeanFactory beanFactory) {
             DsProcessor sessionProcessor = new DsJakartaSessionProcessor();
             DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor();
             spelExpressionProcessor.setBeanResolver(new BeanFactoryResolver(beanFactory));
    +        spelExpressionProcessor.setAllowedSpelTypeAccess(properties.getAop().getAllowedSpelTypeAccess());
             headerProcessor.setNextProcessor(sessionProcessor);
             sessionProcessor.setNextProcessor(spelExpressionProcessor);
             return headerProcessor;
    
  • dynamic-datasource-spring-boot-common/src/main/java/com/baomidou/dynamic/datasource/spring/boot/autoconfigure/DynamicDatasourceAopProperties.java+8 0 modified
    @@ -38,4 +38,12 @@ public class DynamicDatasourceAopProperties {
          * aop allowedPublicOnly
          */
         private Boolean allowedPublicOnly = true;
    +    /**
    +     * Whether to allow SpEL type references (e.g. T(java.lang.Runtime)) and constructor
    +     * expressions in datasource key expressions resolved by DsSpelExpressionProcessor.
    +     * Defaults to false (restricted / safe mode) to prevent SpEL injection attacks.
    +     * Set to true only if your application genuinely requires such expressions and you
    +     * fully understand the security risk.
    +     */
    +    private Boolean allowedSpelTypeAccess = false;
     }
    \ No newline at end of file
    
  • dynamic-datasource-spring-boot-starter/src/main/java/com/baomidou/dynamic/datasource/spring/boot/autoconfigure/DynamicDataSourceAopConfiguration.java+1 0 modified
    @@ -66,6 +66,7 @@ public DsProcessor dsProcessor(BeanFactory beanFactory) {
             DsProcessor sessionProcessor = new DsSessionProcessor();
             DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor();
             spelExpressionProcessor.setBeanResolver(new BeanFactoryResolver(beanFactory));
    +        spelExpressionProcessor.setAllowedSpelTypeAccess(properties.getAop().getAllowedSpelTypeAccess());
             headerProcessor.setNextProcessor(sessionProcessor);
             sessionProcessor.setNextProcessor(spelExpressionProcessor);
             return headerProcessor;
    
  • dynamic-datasource-spring/src/main/java/com/baomidou/dynamic/datasource/processor/DsSpelExpressionProcessor.java+32 0 modified
    @@ -22,12 +22,14 @@
     import org.springframework.core.DefaultParameterNameDiscoverer;
     import org.springframework.core.ParameterNameDiscoverer;
     import org.springframework.expression.BeanResolver;
    +import org.springframework.expression.EvaluationException;
     import org.springframework.expression.ExpressionParser;
     import org.springframework.expression.ParserContext;
     import org.springframework.expression.spel.standard.SpelExpressionParser;
     import org.springframework.expression.spel.support.StandardEvaluationContext;
     
     import java.lang.reflect.Method;
    +import java.util.Collections;
     
     /**
      * SpEL表达式处理器
    @@ -69,6 +71,18 @@ public String getExpressionSuffix() {
             }
         };
         private BeanResolver beanResolver;
    +    /**
    +     * Whether to allow SpEL type references (e.g. {@code T(java.lang.Runtime)}) and constructor
    +     * expressions in datasource key expressions.
    +     * <p>
    +     * Defaults to {@code false} (restricted / safe mode). When {@code false}, any attempt to use
    +     * {@code T(...)} type-references or {@code new} constructor expressions will throw an
    +     * {@link EvaluationException}, preventing potential SpEL-injection / RCE attacks.
    +     * <p>
    +     * Set to {@code true} only if your application genuinely requires such expressions and you
    +     * fully understand the security implications.
    +     */
    +    private boolean allowedSpelTypeAccess = false;
     
         @Override
         public boolean matches(String key) {
    @@ -82,10 +96,28 @@ public String doDetermineDatasource(MethodInvocation invocation, String key) {
             ExpressionRootObject rootObject = new ExpressionRootObject(method, arguments, invocation.getThis());
             StandardEvaluationContext context = new MethodBasedEvaluationContext(rootObject, method, arguments, NAME_DISCOVERER);
             context.setBeanResolver(beanResolver);
    +        if (!allowedSpelTypeAccess) {
    +            // Prevent SpEL injection: block T(...) type references and new instance creation
    +            context.setTypeLocator(typeName -> {
    +                throw new EvaluationException("Type access is not allowed in DS SpEL expressions: " + typeName);
    +            });
    +            context.setConstructorResolvers(Collections.emptyList());
    +        }
             final Object value = PARSER.parseExpression(key, parserContext).getValue(context);
             return value == null ? null : value.toString();
         }
     
    +    /**
    +     * Allow or restrict SpEL type references ({@code T(...)}) and constructor expressions in
    +     * datasource key resolution. Defaults to {@code false} (restricted). Enable only when
    +     * strictly necessary and you accept the associated security risk.
    +     *
    +     * @param allowedSpelTypeAccess {@code true} to allow type access, {@code false} to block it
    +     */
    +    public void setAllowedSpelTypeAccess(boolean allowedSpelTypeAccess) {
    +        this.allowedSpelTypeAccess = allowedSpelTypeAccess;
    +    }
    +
         /**
          * 设置解析上下文
          *
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

0

No linked articles in our index yet.