VYPR
Medium severity6.4NVD Advisory· Published Jan 21, 2025· Updated Apr 15, 2026

CVE-2024-51417

CVE-2024-51417

Description

An issue in System.Linq.Dynamic.Core before 1.6.0 allows remote access to properties on reflection types and static properties/fields.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
System.Linq.Dynamic.CoreNuGet
< 1.6.01.6.0

Patches

2
49b6cf0909cf

Fix CVE-2024-51417 (#870)

18 files changed · +294 76
  • src/System.Linq.Dynamic.Core/CustomTypeProviders/AbstractDynamicLinqCustomTypeProvider.cs+29 29 modified
    @@ -1,6 +1,5 @@
     using System.Collections.Generic;
     using System.Diagnostics.CodeAnalysis;
    -using System.Linq.Dynamic.Core.Extensions;
     using System.Linq.Dynamic.Core.Validation;
     using System.Reflection;
     
    @@ -13,11 +12,25 @@ namespace System.Linq.Dynamic.Core.CustomTypeProviders;
     public abstract class AbstractDynamicLinqCustomTypeProvider
     {
         /// <summary>
    -    /// Finds the unique types marked with DynamicLinqTypeAttribute.
    +    /// Additional types which should also be resolved.
    +    /// </summary>
    +    protected readonly IList<Type> AdditionalTypes;
    +
    +    /// <summary>
    +    /// Initializes a new instance of the <see cref="AbstractDynamicLinqCustomTypeProvider"/> class.
    +    /// </summary>
    +    /// <param name="additionalTypes">A list of additional types (without the DynamicLinqTypeAttribute annotation) which should also be resolved.</param>
    +    protected AbstractDynamicLinqCustomTypeProvider(IList<Type> additionalTypes)
    +    {
    +        AdditionalTypes = Check.NotNull(additionalTypes);
    +    }
    +
    +    /// <summary>
    +    /// Finds the unique types annotated with DynamicLinqTypeAttribute.
         /// </summary>
         /// <param name="assemblies">The assemblies to process.</param>
         /// <returns><see cref="IEnumerable{Type}" /></returns>
    -    protected IEnumerable<Type> FindTypesMarkedWithDynamicLinqTypeAttribute(IEnumerable<Assembly> assemblies)
    +    protected Type[] FindTypesMarkedWithDynamicLinqTypeAttribute(IEnumerable<Assembly> assemblies)
         {
             Check.NotNull(assemblies);
     #if !NET35
    @@ -27,7 +40,7 @@ protected IEnumerable<Type> FindTypesMarkedWithDynamicLinqTypeAttribute(IEnumera
         }
     
         /// <summary>
    -    /// Resolve any type which is registered in the current application domain.
    +    /// Resolve a type which is annotated with DynamicLinqTypeAttribute or when the type is listed in AdditionalTypes.
         /// </summary>
         /// <param name="assemblies">The assemblies to inspect.</param>
         /// <param name="typeName">The typename to resolve.</param>
    @@ -37,20 +50,13 @@ protected IEnumerable<Type> FindTypesMarkedWithDynamicLinqTypeAttribute(IEnumera
             Check.NotNull(assemblies);
             Check.NotEmpty(typeName);
     
    -        foreach (var assembly in assemblies)
    -        {
    -            var resolvedType = assembly.GetType(typeName, false, true);
    -            if (resolvedType != null)
    -            {
    -                return resolvedType;
    -            }
    -        }
    -
    -        return null;
    +        var types = FindTypesMarkedWithDynamicLinqTypeAttribute(assemblies).Union(AdditionalTypes);
    +        return types.FirstOrDefault(t => t.FullName == typeName);
         }
     
         /// <summary>
    -    /// Resolve a type by the simple name which is registered in the current application domain.
    +    /// Resolve a type which is annotated with DynamicLinqTypeAttribute by the simple (short) name.
    +    /// Also when the type is listed in AdditionalTypes.
         /// </summary>
         /// <param name="assemblies">The assemblies to inspect.</param>
         /// <param name="simpleTypeName">The simple typename to resolve.</param>
    @@ -60,22 +66,16 @@ protected IEnumerable<Type> FindTypesMarkedWithDynamicLinqTypeAttribute(IEnumera
             Check.NotNull(assemblies);
             Check.NotEmpty(simpleTypeName);
     
    -        foreach (var assembly in assemblies)
    -        {
    -            var fullNames = assembly.GetTypes().Select(t => t.FullName!).Distinct();
    -            var firstMatchingFullname = fullNames.FirstOrDefault(fn => fn.EndsWith($".{simpleTypeName}"));
    +        var types = FindTypesMarkedWithDynamicLinqTypeAttribute(assemblies);
    +        var fullNames = types.Select(t => t.FullName!).Distinct().ToArray();
    +        var firstMatchingFullname = fullNames.FirstOrDefault(fn => fn.EndsWith($".{simpleTypeName}"));
     
    -            if (firstMatchingFullname != null)
    -            {
    -                var resolvedType = assembly.GetType(firstMatchingFullname, false, true);
    -                if (resolvedType != null)
    -                {
    -                    return resolvedType;
    -                }
    -            }
    +        if (firstMatchingFullname == null)
    +        {
    +            return null;
             }
     
    -        return null;
    +        return types.FirstOrDefault(t => t.FullName == firstMatchingFullname);
         }
     
     #if (UAP10_0 || NETSTANDARD)
    @@ -147,7 +147,7 @@ protected Type[] GetAssemblyTypesWithDynamicLinqTypeAttribute(IEnumerable<Assemb
                 }
                 catch (ReflectionTypeLoadException reflectionTypeLoadException)
                 {
    -                definedTypes = reflectionTypeLoadException.Types.WhereNotNull().ToArray();
    +                definedTypes = reflectionTypeLoadException.Types.OfType<Type>().ToArray();
                 }
                 catch
                 {
    
  • src/System.Linq.Dynamic.Core/CustomTypeProviders/DefaultDynamicLinqCustomTypeProvider.cs+15 6 modified
    @@ -10,8 +10,6 @@ namespace System.Linq.Dynamic.Core.CustomTypeProviders;
     /// 
     /// Scans the current AppDomain for all types marked with <see cref="DynamicLinqTypeAttribute"/>, and adds them as custom Dynamic Link types.
     ///
    -/// Also provides functionality to resolve a Type in the current Application Domain.
    -///
     /// This class is used as default for full .NET Framework and .NET Core App 2.x and higher.
     /// </summary>
     public class DefaultDynamicLinqCustomTypeProvider : AbstractDynamicLinqCustomTypeProvider, IDynamicLinkCustomTypeProvider
    @@ -22,12 +20,12 @@ public class DefaultDynamicLinqCustomTypeProvider : AbstractDynamicLinqCustomTyp
         private HashSet<Type>? _cachedCustomTypes;
         private Dictionary<Type, List<MethodInfo>>? _cachedExtensionMethods;
     
    -    /// <summary>
    +     /// <summary>
         /// Initializes a new instance of the <see cref="DefaultDynamicLinqCustomTypeProvider"/> class.
         /// Backwards compatibility for issue https://github.com/zzzprojects/System.Linq.Dynamic.Core/issues/830.
         /// </summary>
         /// <param name="cacheCustomTypes">Defines whether to cache the CustomTypes (including extension methods) which are found in the Application Domain. Default set to 'true'.</param>
    -    [Obsolete("Please use the DefaultDynamicLinqCustomTypeProvider(ParsingConfig config, bool cacheCustomTypes = true) constructor.")]
    +    [Obsolete("Please use the DefaultDynamicLinqCustomTypeProvider(ParsingConfig config, IList<Type> additionalTypes, bool cacheCustomTypes = true) constructor.")]
         public DefaultDynamicLinqCustomTypeProvider(bool cacheCustomTypes = true) : this(ParsingConfig.Default, cacheCustomTypes)
         {
         }
    @@ -37,7 +35,17 @@ public DefaultDynamicLinqCustomTypeProvider(bool cacheCustomTypes = true) : this
         /// </summary>
         /// <param name="config">The parsing configuration.</param>
         /// <param name="cacheCustomTypes">Defines whether to cache the CustomTypes (including extension methods) which are found in the Application Domain. Default set to 'true'.</param>
    -    public DefaultDynamicLinqCustomTypeProvider(ParsingConfig config, bool cacheCustomTypes = true)
    +    public DefaultDynamicLinqCustomTypeProvider(ParsingConfig config, bool cacheCustomTypes = true) : this(config, new List<Type>(), cacheCustomTypes)
    +    {
    +    }
    +
    +    /// <summary>
    +    /// Initializes a new instance of the <see cref="DefaultDynamicLinqCustomTypeProvider"/> class.
    +    /// </summary>
    +    /// <param name="config">The parsing configuration.</param>
    +    /// <param name="additionalTypes">A list of additional types (without the DynamicLinqTypeAttribute annotation) which should also be resolved.</param>
    +    /// <param name="cacheCustomTypes">Defines whether to cache the CustomTypes (including extension methods) which are found in the Application Domain. Default set to 'true'.</param>
    +    public DefaultDynamicLinqCustomTypeProvider(ParsingConfig config, IList<Type> additionalTypes, bool cacheCustomTypes = true) : base(additionalTypes)
         {
             _assemblyHelper = new DefaultAssemblyHelper(Check.NotNull(config));
             _cacheCustomTypes = cacheCustomTypes;
    @@ -96,7 +104,8 @@ public Dictionary<Type, List<MethodInfo>> GetExtensionMethods()
         private HashSet<Type> GetCustomTypesInternal()
         {
             IEnumerable<Assembly> assemblies = _assemblyHelper.GetAssemblies();
    -        return new HashSet<Type>(FindTypesMarkedWithDynamicLinqTypeAttribute(assemblies));
    +        var types = FindTypesMarkedWithDynamicLinqTypeAttribute(assemblies).Union(AdditionalTypes);
    +        return new HashSet<Type>(types);
         }
     
         private Dictionary<Type, List<MethodInfo>> GetExtensionMethodsInternal()
    
  • src/System.Linq.Dynamic.Core/CustomTypeProviders/IDynamicLinkCustomTypeProvider.cs+2 2 modified
    @@ -2,9 +2,9 @@
     {
         /// <summary>
         /// Interface for providing functionality to find custom types for or resolve any type.
    -    /// Note that this interface will be marked obsolete in the next version. Use <see cref="IDynamicLinqCustomTypeProvider"/> instead.
         /// </summary>
    +    [Obsolete("Please use the IDynamicLinqCustomTypeProvider interface instead.")]
         public interface IDynamicLinkCustomTypeProvider : IDynamicLinqCustomTypeProvider
         {
         }
    -}
    +}
    \ No newline at end of file
    
  • src/System.Linq.Dynamic.Core/Extensions/LinqExtensions.cs+0 16 removed
    @@ -1,16 +0,0 @@
    -using System.Collections.Generic;
    -using System.Diagnostics.CodeAnalysis;
    -using System.Linq.Dynamic.Core.Validation;
    -
    -namespace System.Linq.Dynamic.Core.Extensions;
    -
    -[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
    -internal static class LinqExtensions
    -{
    -    public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T?> sequence)
    -    {
    -        Check.NotNull(sequence);
    -
    -        return sequence.Where(e => e != null)!;
    -    }
    -}
    \ No newline at end of file
    
  • src/System.Linq.Dynamic.Core/Parser/PredefinedTypesHelper.cs+1 1 modified
    @@ -28,7 +28,7 @@ internal static class PredefinedTypesHelper
     
         public static readonly IDictionary<Type, int> PredefinedTypes = new ConcurrentDictionary<Type, int>(new Dictionary<Type, int>
         {
    -        { typeof(object), 0 },
    +        // { typeof(object), 0 }, Removed because of CVE-2024-51417
             { typeof(bool), 0 },
             { typeof(char), 0 },
             { typeof(string), 0 },
    
  • src/System.Linq.Dynamic.Core/ParsingConfig.cs+19 0 modified
    @@ -71,6 +71,25 @@ public IDynamicLinkCustomTypeProvider? CustomTypeProvider
             }
         }
     
    +    /// <summary>
    +    /// Sets the CustomTypeProvider to <see cref="DefaultDynamicLinqCustomTypeProvider"/>.
    +    /// </summary>
    +    /// <param name="cacheCustomTypes">Defines whether to cache the CustomTypes (including extension methods) which are found in the Application Domain. Default set to <c>true</c>.</param>
    +    public void UseDefaultDynamicLinqCustomTypeProvider(bool cacheCustomTypes = true)
    +    {
    +        _customTypeProvider = new DefaultDynamicLinqCustomTypeProvider(this, cacheCustomTypes);
    +    }
    +
    +    /// <summary>
    +    /// Sets the CustomTypeProvider to <see cref="DefaultDynamicLinqCustomTypeProvider"/>.
    +    /// </summary>
    +    /// <param name="cacheCustomTypes">Defines whether to cache the CustomTypes (including extension methods) which are found in the Application Domain. Default set to <c>true</c>.</param>
    +    /// <param name="additionalTypes">A list of additional types (without the DynamicLinqTypeAttribute annotation) which should also be resolved.</param>
    +    public void UseDefaultDynamicLinqCustomTypeProvider(IList<Type> additionalTypes, bool cacheCustomTypes = true)
    +    {
    +        _customTypeProvider = new DefaultDynamicLinqCustomTypeProvider(this, additionalTypes, cacheCustomTypes);
    +    }
    +
         /// <summary>
         /// Load additional assemblies from the current domain base directory.
         /// Note: only used when full .NET Framework and .NET Core App 2.x and higher.
    
  • test/System.Linq.Dynamic.Core.Tests/CustomTypeProviders/DefaultDynamicLinqCustomTypeProviderTests.cs+9 2 modified
    @@ -1,4 +1,5 @@
    -using System.IO;
    +using System.Collections.Generic;
    +using System.IO;
     using System.Linq.Dynamic.Core.CustomTypeProviders;
     using FluentAssertions;
     using NFluent;
    @@ -8,11 +9,17 @@ namespace System.Linq.Dynamic.Core.Tests.CustomTypeProviders;
     
     public class DefaultDynamicLinqCustomTypeProviderTests
     {
    +    private readonly IList<Type> _additionalTypes = new List<Type>
    +    {
    +        typeof(DirectoryInfo),
    +        typeof(DefaultDynamicLinqCustomTypeProviderTests)
    +    };
    +
         private readonly DefaultDynamicLinqCustomTypeProvider _sut;
     
         public DefaultDynamicLinqCustomTypeProviderTests()
         {
    -        _sut = new DefaultDynamicLinqCustomTypeProvider(ParsingConfig.Default);
    +        _sut = new DefaultDynamicLinqCustomTypeProvider(ParsingConfig.Default, _additionalTypes);
         }
     
         [Fact]
    
  • test/System.Linq.Dynamic.Core.Tests/DynamicClassTest.cs+2 1 modified
    @@ -281,7 +281,8 @@ public void DynamicClassArray_Issue593_Fails()
             isValid.Should().BeFalse(); // This should actually be true, but fails. For solution see Issue593_Solution1 and Issue593_Solution2.
         }
     
    -    [SkipIfGitHubActions]
    +    // [SkipIfGitHubActions]
    +    [Fact(Skip = "867")]
         public void DynamicClassArray_Issue593_Solution1()
         {
             // Arrange
    
  • test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs+1 1 modified
    @@ -1058,7 +1058,7 @@ public void DynamicExpressionParser_ParseLambda_StringLiteral_QuotationMark()
             Assert.Equal(expectedRightValue, rightValue);
         }
     
    -    [Fact]
    +    [Fact(Skip = "867")]
         public void DynamicExpressionParser_ParseLambda_TupleToStringMethodCall_ReturnsStringLambdaExpression()
         {
             var expression = DynamicExpressionParser.ParseLambda(
    
  • test/System.Linq.Dynamic.Core.Tests/Entities/Worker.cs+4 1 modified
    @@ -1,5 +1,8 @@
    -namespace System.Linq.Dynamic.Core.Tests.Entities
    +using System.Linq.Dynamic.Core.CustomTypeProviders;
    +
    +namespace System.Linq.Dynamic.Core.Tests.Entities
     {
    +    [DynamicLinqType]
         public class Worker : BaseEmployee
         {
             public string Other { get; set; }
    
  • test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs+11 3 modified
    @@ -13,6 +13,7 @@
     
     namespace System.Linq.Dynamic.Core.Tests
     {
    +    [DynamicLinqType]
         public enum TestEnumPublic : sbyte
         {
             Var1 = 0,
    @@ -25,6 +26,7 @@ public enum TestEnumPublic : sbyte
     
         public partial class ExpressionTests
         {
    +        [DynamicLinqType]
             public enum TestEnum2 : sbyte
             {
                 Var1 = 0,
    @@ -919,6 +921,9 @@ public void ExpressionTests_Enum_Property_Equality_Using_PublicEnum_And_FullName
             public void ExpressionTests_Enum_Property_Equality_Using_Enum_And_FullName_Inline()
             {
                 // Arrange
    +            var config = new ParsingConfig();
    +            config.UseDefaultDynamicLinqCustomTypeProvider([typeof(TestEnum2)]);
    +
                 var qry = new List<TestEnumClass> { new TestEnumClass { B = TestEnum2.Var2 } }.AsQueryable();
                 string enumType = typeof(TestEnum2).FullName!;
     
    @@ -948,7 +953,7 @@ public void ExpressionTests_Enum_Property_Equality_Using_PublicEnum_Name_Inline(
             }
     
             [Fact]
    -        public void ExpressionTests_Enum_Property_Equality_Using_Enum_Name_Inline_Should_Throw_Exception()
    +        public void ExpressionTests_Enum_Property_Equality_Using_Enum_Name_Inline_ShouldBeOk()
             {
                 // Arrange
                 var config = new ParsingConfig
    @@ -962,7 +967,7 @@ public void ExpressionTests_Enum_Property_Equality_Using_Enum_Name_Inline_Should
                 Action a = () => qry.Where(config, $"{enumType}.Var2 == it.B").ToDynamicArray();
     
                 // Assert
    -            a.Should().Throw<Exception>();
    +            a.Should().NotThrow();
             }
     
             [Fact]
    @@ -1031,7 +1036,10 @@ public void ExpressionTests_Enum_NullableProperty()
             [Fact]
             public void ExpressionTests_Enum_MoreTests()
             {
    -            var config = new ParsingConfig();
    +            var config = new ParsingConfig
    +            {
    +                ResolveTypesBySimpleName = true
    +            };
     
                 // Arrange
                 var lst = new List<TestEnum> { TestEnum.Var1, TestEnum.Var2, TestEnum.Var3, TestEnum.Var4, TestEnum.Var5, TestEnum.Var6 };
    
  • test/System.Linq.Dynamic.Core.Tests/Helpers/Models/AppSettings.cs+45 0 added
    @@ -0,0 +1,45 @@
    +using System.Collections.Generic;
    +using System.Linq.Dynamic.Core.CustomTypeProviders;
    +
    +namespace System.Linq.Dynamic.Core.Tests.Helpers.Models
    +{
    +    public static class AppSettings
    +    {
    +        public static Dictionary<string, string> SettingsProp { get; } = new()
    +        {
    +            { "jwt", "test" }
    +        };
    +
    +        public static Dictionary<string, string> SettingsField = new()
    +        {
    +            { "jwt", "test" }
    +        };
    +    }
    +
    +    [DynamicLinqType]
    +    public static class AppSettings2
    +    {
    +        public static Dictionary<string, string> SettingsProp { get; } = new()
    +        {
    +            { "jwt", "test" }
    +        };
    +
    +        public static Dictionary<string, string> SettingsField = new()
    +        {
    +            { "jwt", "test" }
    +        };
    +    }
    +
    +    public class AppSettings3
    +    {
    +        public static Dictionary<string, string> SettingsProp { get; } = new()
    +        {
    +            { "jwt", "test" }
    +        };
    +
    +        public static Dictionary<string, string> SettingsField = new()
    +        {
    +            { "jwt", "test" }
    +        };
    +    }
    +}
    \ No newline at end of file
    
  • test/System.Linq.Dynamic.Core.Tests/Parser/ExpressionParserTests.cs+1 1 modified
    @@ -346,7 +346,7 @@ public void Parse_NullableShouldReturnNullable(string expression, object resultT
         [Theory]
         [InlineData("it.MainCompany.Name != null", "(company.MainCompany.Name != null)")]
         [InlineData("@MainCompany.Companies.Count() > 0", "(company.MainCompany.Companies.Count() > 0)")]
    -    [InlineData("Company.Equals(null, null)", "Equals(null, null)")]
    +    // [InlineData("Company.Equals(null, null)", "Equals(null, null)")] issue 867
         [InlineData("MainCompany.Name", "company.MainCompany.Name")]
         [InlineData("Name", "company.Name")]
         [InlineData("company.Name", "company.Name")]
    
  • test/System.Linq.Dynamic.Core.Tests/Parser/MethodFinderTest.cs+2 2 modified
    @@ -7,14 +7,14 @@ namespace System.Linq.Dynamic.Core.Tests.Parser;
     
     public class MethodFinderTest
     {
    -    [Fact]
    +    [Fact(Skip = "867")]
         public void MethodsOfDynamicLinqAndSystemLinqShouldBeEqual()
         {
             Expression<Func<int?, string?>> expr = x => x.ToString();
                 
             var selector = "ToString()";
             var prm = Parameter(typeof(int?));
    -        var parser = new ExpressionParser(new[] { prm }, selector, new object[] { }, ParsingConfig.Default);
    +        var parser = new ExpressionParser([prm], selector, [], ParsingConfig.Default);
             var expr1 = parser.Parse(null);
                 
             Assert.Equal(((MethodCallExpression)expr.Body).Method.DeclaringType, ((MethodCallExpression)expr1).Method.DeclaringType);
    
  • test/System.Linq.Dynamic.Core.Tests/QueryableTests.Is,OfType,As,Cast.cs+9 3 modified
    @@ -1,4 +1,5 @@
     using System.Collections.Generic;
    +using System.Linq.Dynamic.Core.CustomTypeProviders;
     using System.Linq.Dynamic.Core.Exceptions;
     using System.Linq.Dynamic.Core.Tests.Entities;
     using FluentAssertions;
    @@ -98,6 +99,7 @@ public void OfType_Dynamic_WithFullName_UseParameterizedNamesInDynamicQuery(bool
     
             internal class Base { }
     
    +        [DynamicLinqType]
             internal class DerivedA : Base { }
     
             internal class DerivedB : Base { }
    @@ -294,7 +296,8 @@ public void As_Dynamic_ActingOnProperty_NullableInt()
                 countAsDynamic.Should().Be(count);
             }
     
    -        public enum TestEnum
    +        [DynamicLinqType]
    +        public enum TestEnumForThisTest
             {
                 None = 0,
     
    @@ -305,10 +308,10 @@ public enum TestEnum
             public void As_Dynamic_ActingOnProperty_NullableEnum()
             {
                 // Assign
    -            var nullableEnumType = $"{typeof(TestEnum).FullName}?";
    +            var nullableEnumType = $"{typeof(TestEnumForThisTest).FullName}?";
                 var qry = new[]
                 {
    -                new { Value = TestEnum.X }
    +                new { Value = TestEnumForThisTest.X }
                 }.AsQueryable();
     
                 // Act
    @@ -365,7 +368,10 @@ public void As_Dynamic_ActingOnProperty_WithType()
                 countAsDynamic.Should().Be(1);
             }
     
    +        [DynamicLinqType]
             public class AS_A { }
    +
    +        [DynamicLinqType]
             public class AS_B : AS_A
             {
                 public string MyProperty { get; set; }
    
  • test/System.Linq.Dynamic.Core.Tests/QueryableTests.Select.cs+9 1 modified
    @@ -1,6 +1,7 @@
     using System.Collections;
     using System.Collections.Generic;
     using System.IO;
    +using System.Linq.Dynamic.Core.CustomTypeProviders;
     using System.Linq.Dynamic.Core.Exceptions;
     using System.Linq.Dynamic.Core.Tests.Helpers.Models;
     using FluentAssertions;
    @@ -19,6 +20,7 @@ namespace System.Linq.Dynamic.Core.Tests
     {
         public partial class QueryableTests
         {
    +        [DynamicLinqType]
             public class Example
             {
                 public int Field;
    @@ -29,10 +31,12 @@ public class Example
                 public int Sec { get; set; }
                 public int? SecNull { get; set; }
     
    +            [DynamicLinqType]
                 public class NestedDto
                 {
                     public string Name { get; set; }
     
    +                [DynamicLinqType]
                     public class NestedDto2
                     {
                         public string Name2 { get; set; }
    @@ -324,7 +328,11 @@ public void Select_Dynamic_IntoTypeWithNullableParameterInConstructor()
             public void Select_Dynamic_SystemType1()
             {
                 // Arrange
    -            var config = new ParsingConfig { AllowNewToEvaluateAnyType = true };
    +            var config = new ParsingConfig
    +            {
    +                AllowNewToEvaluateAnyType = true
    +            };
    +            config.UseDefaultDynamicLinqCustomTypeProvider([typeof(DirectoryInfo)]);
                 var queryable = new[] { "test" }.AsQueryable();
     
                 // Act
    
  • test/System.Linq.Dynamic.Core.Tests/SecurityTests.cs+129 6 modified
    @@ -1,6 +1,5 @@
     using System.IO;
     using System.Linq.Dynamic.Core.Exceptions;
    -using System.Net;
     using System.Reflection;
     using FluentAssertions;
     using Xunit;
    @@ -26,13 +25,13 @@ public void MethodsShouldOnlyBeCallableOnPredefinedTypes_Test1()
         {
             // Arrange
             var baseQuery = new[] { 1, 2, 3 }.AsQueryable();
    -        string predicate = "\"\".GetType().Assembly.DefinedTypes.Where(it.name == \"Assembly\").First().DeclaredMethods.Where(it.Name == \"GetName\").First().Invoke(\"\".GetType().Assembly, new Object[] {} ).Name.ToString() != \"Test\"";
    +        var predicate = "\"\".GetType().Assembly.DefinedTypes.Where(it.name == \"Assembly\").First().DeclaredMethods.Where(it.Name == \"GetName\").First().Invoke(\"\".GetType().Assembly, new Object[] {} ).Name.ToString() != \"Test\"";
     
             // Act
             Action action = () => baseQuery.OrderBy(predicate);
     
             // Assert
    -        action.Should().Throw<ParseException>().WithMessage("Methods on type 'MethodBase' are not accessible");
    +        action.Should().Throw<ParseException>().WithMessage("Methods on type 'Object' are not accessible");
         }
     
         [Fact]
    @@ -41,16 +40,15 @@ public void MethodsShouldOnlyBeCallableOnPredefinedTypes_Test2()
             // Arrange
             var messages = new[]
             {
    -            new Message("Alice", "Bob"),
    -            new Message("Bob", "Alice")
    +            new Message("Alice", "Bob")
             }.AsQueryable();
     
             Action action = () => messages.Where(
                 "\"\".GetType().Assembly.GetType(\"System.AppDomain\").GetMethods()[104].Invoke(\"\".GetType().Assembly.GetType(\"System.AppDomain\").GetProperty(\"CurrentDomain\").GetValue(null), \"System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;System.Diagnostics.Process\".Split(\";\".ToCharArray())).GetType().GetMethods()[80].Invoke(null, \"cmd;/T:4A /K whoami && echo was HACKED\".Split(\";\".ToCharArray()))"
             );
     
             // Assert
    -        action.Should().Throw<ParseException>().WithMessage($"Methods on type 'Assembly' are not accessible");
    +        action.Should().Throw<ParseException>().WithMessage($"Methods on type 'Object' are not accessible");
         }
     
         [Theory]
    @@ -64,4 +62,129 @@ public void DynamicExpressionParser_ParseLambda_IllegalMethodCall_ThrowsExceptio
             // Assert
             action.Should().Throw<ParseException>().WithMessage($"Methods on type '{type}' are not accessible");
         }
    +
    +    [Theory]
    +    [InlineData("c => string.Join(\"_\", c.GetType().Assembly.DefinedTypes.SelectMany(t => t.CustomAttributes).Select(a => a.AttributeType).Select(t => t.AssemblyQualifiedName))")]
    +    [InlineData("c => string.Join(\"_\", c.GetType().Assembly.DefinedTypes.Select(t => t.BaseType).Select(t => t.AssemblyQualifiedName))")]
    +    [InlineData("c => string.Join(\"_\", c.GetType().Assembly.FullName))")]
    +    public void UsingSystemReflectionAssembly_ThrowsException(string selector)
    +    {
    +        // Arrange
    +        var queryable = new[]
    +        {
    +            new Message("Alice", "Bob")
    +        }.AsQueryable();
    +
    +        // Act
    +        Action action = () => queryable.Select(selector);
    +
    +        // Assert
    +        action.Should().Throw<ParseException>().WithMessage("Methods on type 'Object' are not accessible");
    +    }
    +
    +    [Theory]
    +    [InlineData("System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsProp[\"jwt\"]")]
    +    [InlineData("System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsField[\"jwt\"]")]
    +    [InlineData("c => System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsProp[\"jwt\"]")]
    +    [InlineData("c => System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsField[\"jwt\"]")]
    +    public void UsingStaticClassAsType_ThrowsException(string selector)
    +    {
    +        // Arrange
    +        var queryable = new[]
    +        {
    +            new Message("Alice", "Bob")
    +        }.AsQueryable();
    +
    +        // Act
    +        Action action = () => queryable.Select(selector);
    +
    +        // Assert
    +        action.Should().Throw<ParseException>().WithMessage("Type 'System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings' not found");
    +    }
    +
    +    [Theory]
    +    [InlineData("new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3().SettingsProp[\"jwt\"]")]
    +    [InlineData("new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3().SettingsField[\"jwt\"]")]
    +    [InlineData("c => new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3().SettingsProp[\"jwt\"]")]
    +    [InlineData("c => new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3().SettingsField[\"jwt\"]")]
    +    public void UsingClassAsType_ThrowsException(string selector)
    +    {
    +        // Arrange
    +        var queryable = new[]
    +        {
    +            new Message("Alice", "Bob")
    +        }.AsQueryable();
    +
    +        // Act
    +        Action action = () => queryable.Select(selector);
    +
    +        // Assert
    +        action.Should().Throw<ParseException>().WithMessage("Type 'System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3' not found");
    +    }
    +
    +    [Theory]
    +    [InlineData("System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsProp[\"jwt\"]")]
    +    [InlineData("System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsField[\"jwt\"]")]
    +    [InlineData("c => System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsProp[\"jwt\"]")]
    +    [InlineData("c => System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings.SettingsField[\"jwt\"]")]
    +    public void UsingStaticClassAsType_WhenAddedToDefaultDynamicLinqCustomTypeProvider_ShouldBeOk(string selector)
    +    {
    +        // Arrange
    +        var config = new ParsingConfig();
    +        config.UseDefaultDynamicLinqCustomTypeProvider([typeof(Helpers.Models.AppSettings), typeof(Helpers.Models.AppSettings3)]);
    +
    +        var queryable = new[]
    +        {
    +            new Message("Alice", "Bob")
    +        }.AsQueryable();
    +
    +        // Act
    +        Action action = () => queryable.Select(config, selector);
    +
    +        // Assert
    +        action.Should().NotThrow();
    +    }
    +
    +    [Theory(Skip = "873")]
    +    [InlineData("new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3()", "SettingsProp[\"jwt\"]")]
    +    [InlineData("new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3()", "SettingsField[\"jwt\"]")]
    +    [InlineData("c => new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3()", "SettingsProp[\"jwt\"]")]
    +    [InlineData("c => new System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings3()", "SettingsField[\"jwt\"]")]
    +    public void UsingClassAsType_WhenAddedToDefaultDynamicLinqCustomTypeProvider_ShouldBeOk(string selector1, string selector2)
    +    {
    +        // Arrange
    +        var config = new ParsingConfig();
    +        config.UseDefaultDynamicLinqCustomTypeProvider([typeof(Helpers.Models.AppSettings), typeof(Helpers.Models.AppSettings3)]);
    +
    +        var queryable = new[]
    +        {
    +            new Message("Alice", "Bob")
    +        }.AsQueryable();
    +
    +        // Act
    +        Action action = () => queryable.Select(config, selector1).Select(config, selector2);
    +
    +        // Assert
    +        action.Should().NotThrow();
    +    }
    +
    +    [Theory]
    +    [InlineData("System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings2.SettingsProp[\"jwt\"]")]
    +    [InlineData("System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings2.SettingsField[\"jwt\"]")]
    +    [InlineData("c => System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings2.SettingsProp[\"jwt\"]")]
    +    [InlineData("c => System.Linq.Dynamic.Core.Tests.Helpers.Models.AppSettings2.SettingsField[\"jwt\"]")]
    +    public void UsingStaticClassWithDynamicTypeAttribute_ShouldBeOk(string selector)
    +    {
    +        // Arrange
    +        var queryable = new[]
    +        {
    +            new Message("Alice", "Bob")
    +        }.AsQueryable();
    +
    +        // Act
    +        Action action = () => queryable.Select(selector);
    +
    +        // Assert
    +        action.Should().NotThrow();
    +    }
     }
    \ No newline at end of file
    
  • test/System.Linq.Dynamic.Core.Tests/TestClasses/TestCustomTypeProvider.cs+6 1 modified
    @@ -9,19 +9,24 @@ public class TestCustomTypeProvider : AbstractDynamicLinqCustomTypeProvider, IDy
         {
             private HashSet<Type>? _customTypes;
     
    +        public TestCustomTypeProvider() : base([])
    +        {
    +        }
    +
             public virtual HashSet<Type> GetCustomTypes()
             {
                 if (_customTypes != null)
                 {
                     return _customTypes;
                 }
     
    -            _customTypes = new HashSet<Type>(FindTypesMarkedWithDynamicLinqTypeAttribute(new[] { GetType().GetTypeInfo().Assembly }))
    +            _customTypes = new HashSet<Type>(FindTypesMarkedWithDynamicLinqTypeAttribute([GetType().GetTypeInfo().Assembly]))
                 {
                     typeof(CustomClassWithStaticMethod),
                     typeof(StaticHelper),
                     typeof(StaticHelper.Nested)
                 };
    +
                 return _customTypes;
             }
     
    

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

7

News mentions

0

No linked articles in our index yet.