From a3d2abdba4e6f5af4cdab895aaea3536dc5c0eb6 Mon Sep 17 00:00:00 2001 From: Lucas Falslev Date: Thu, 19 Feb 2026 16:59:51 -0700 Subject: [PATCH 1/6] resolve CA1416 windows-only compile time check --- test/unit/ACLProcessorTest.cs | 6 ++++++ test/unit/CertAbuseProcessorTest.cs | 17 +++++++++++++++++ test/unit/CommonLibHelperTests.cs | 4 +++- test/unit/DomainTrustProcessorTest.cs | 2 ++ test/unit/GPOLocalGroupProcessorTest.cs | 2 ++ test/unit/GroupProcessorTest.cs | 3 +++ test/unit/LDAPUtilsTest.cs | 2 ++ test/unit/LdapPropertyTests.cs | 8 ++++++++ test/unit/LocalGroupProcessorTest.cs | 10 ++++++++++ test/unit/UserRightsAssignmentProcessorTest.cs | 5 +++++ test/unit/WebClientServiceProcessorTest.cs | 2 +- 11 files changed, 59 insertions(+), 2 deletions(-) diff --git a/test/unit/ACLProcessorTest.cs b/test/unit/ACLProcessorTest.cs index 7f7677c52..f6907fd34 100644 --- a/test/unit/ACLProcessorTest.cs +++ b/test/unit/ACLProcessorTest.cs @@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis; using System.DirectoryServices; using System.Linq; +using System.Runtime.Versioning; using System.Security.AccessControl; using System.Threading; using System.Threading.Tasks; @@ -60,6 +61,7 @@ public void ACLProcessor_IsACLProtected_NullNTSD_ReturnsFalse() { Assert.False(result); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task ACLProcessor_TestKnownDataAddMember() { var mockLdapUtils = new MockLdapUtils(); @@ -1421,6 +1423,7 @@ public void Test_ACLProcessor_IsACLProtected_NotProtected() { Assert.False(result); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public void ACLProcessor_CalculateImplicitACLHash_ValidInput_ReturnsCorrectHash() { @@ -1439,6 +1442,7 @@ public void ACLProcessor_CalculateImplicitACLHash_ValidInput_ReturnsCorrectHash( Assert.Equal(expectedHash, result); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public void ACLProcessor_CalculateImplicitACLHash_DifferentInputs_ProducesUniqueHashes() { @@ -1458,6 +1462,7 @@ public void ACLProcessor_CalculateImplicitACLHash_DifferentInputs_ProducesUnique Assert.NotEqual(protectedResult, adminsdResult); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public void ACLProcessor_NullAdminSDHolderHash_Returns_Null_Bool() { @@ -1476,6 +1481,7 @@ public void ACLProcessor_NullAdminSDHolderHash_Returns_Null_Bool() } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public void ACLProcessor_AdminSDHolderHash_Returns_Match() { diff --git a/test/unit/CertAbuseProcessorTest.cs b/test/unit/CertAbuseProcessorTest.cs index 11c2185c1..5c65f1c78 100644 --- a/test/unit/CertAbuseProcessorTest.cs +++ b/test/unit/CertAbuseProcessorTest.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Runtime.Versioning; using System.Security.AccessControl; using System.Security.Principal; using System.Threading; @@ -226,6 +227,7 @@ public async Task CertAbuseProcessor_ProcessEAPermissions_HandlesFailedLookup() Assert.Equal(TargetDomainSid, _receivedCompStatus.ObjectId); } + [SupportedOSPlatform("windows")] public static IEnumerable ProcessEAPermissionsTestData() { return new List { @@ -234,6 +236,7 @@ public static IEnumerable ProcessEAPermissionsTestData() { }; } + [SupportedOSPlatform("windows")] [WindowsOnlyTheory] [MemberData(nameof(ProcessEAPermissionsTestData))] public async Task CertAbuseProcessor_ProcessEAPermissions_ReturnsEmpty(RawAcl dacl) { @@ -335,6 +338,7 @@ public async Task CertAbuseProcessor_ProcessRegistryEnrollmentPermissions_Handle Assert.Equal(TargetDomainSid, _receivedCompStatus.ObjectId); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task CertAbuseProcessor_ProcessRegistryEnrollmentPermissions_ReturnsEmpty_WhenNoOwnerAndNoRules() { var mockSecurityDescriptor = new Mock(null); @@ -405,6 +409,7 @@ public async Task CertAbuseProcessor_ProcessCertTemplates_ReturnsResolvedAndUnre Assert.Contains(invalidCN, results.unresolvedTemplates); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task CertAbuseProcessor_GetRegistryPrincipal_ReturnsFalseForFilteredSID() { var sid = new SecurityIdentifier("S-1-5-3"); @@ -422,6 +427,7 @@ public async Task CertAbuseProcessor_GetRegistryPrincipal_ReturnsFalseForFiltere _mockLdapUtils.VerifyNoOtherCalls(); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task CertAbuseProcessor_GetRegistryPrincipal_CallsResolveIDAndType_ForDomainController() { var expectedPrincipalType = Label.Group; @@ -450,6 +456,7 @@ public async Task CertAbuseProcessor_GetRegistryPrincipal_CallsResolveIDAndType_ _mockLdapUtils.VerifyNoOtherCalls(); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task CertAbuseProcessor_GetRegistryPrincipal_CallsConvertLocalWellKnownPrincipal_ForNonDomainController() { var expectedPrincipalType = Label.Group; @@ -477,6 +484,7 @@ public async Task CertAbuseProcessor_GetRegistryPrincipal_CallsConvertLocalWellK _mockLdapUtils.VerifyNoOtherCalls(); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task CertAbuseProcessor_GetRegistryPrincipal_ResolvesToLocalPrincipal_ForLocalSID() { var expectedPrincipalType = Label.LocalGroup; @@ -504,6 +512,7 @@ public async Task CertAbuseProcessor_GetRegistryPrincipal_ResolvesToLocalPrincip _mockLdapUtils.VerifyNoOtherCalls(); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task CertAbuseProcessor_GetRegistryPrincipal_ResolvesToDomainPrincipal() { var expectedPrincipalType = Label.Group; @@ -558,6 +567,7 @@ public void CertAbuseProcessor_OpenSamServer_CallsOpenServer_Success() { Assert.IsType(result.Value); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task CertAbuseProcessor_GetMachineSid_ReturnsCachedValue() { Cache.AddMachineSid(TargetDomainSid, TargetDomainSid); @@ -586,6 +596,7 @@ public async Task CertAbuseProcessor_GetMachineSid_OpenSAMFailure_ReturnsNull() Assert.Equal(TargetDomainSid, _receivedCompStatus.ObjectId); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task CertAbuseProcessor_GetMachineSid_GetMachineSidFailure_ReturnsNull() { var mockSamServer = new Mock(); @@ -608,6 +619,7 @@ public async Task CertAbuseProcessor_GetMachineSid_GetMachineSidFailure_ReturnsN Assert.Equal(TargetDomainSid, _receivedCompStatus.ObjectId); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task CertAbuseProcessor_GetMachineSid_ReturnsSid() { var mockSamServer = new Mock(); @@ -629,6 +641,7 @@ public async Task CertAbuseProcessor_GetMachineSid_ReturnsSid() { Assert.Equal(TargetDomainSid, _receivedCompStatus.ObjectId); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task CertAbuseProcessor_CreateEnrollmentAgentRestriction_NullOpaque_ReturnsFalse() { var nullOpaqueAce = new CommonAce( @@ -649,6 +662,7 @@ public async Task CertAbuseProcessor_CreateEnrollmentAgentRestriction_NullOpaque _mockLdapUtils.VerifyNoOtherCalls(); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task CertAbuseProcessor_CreateEnrollmentAgentRestriction_UnresolvedTemplate_ReturnsFalse() { var emptyOpaqueAce = new CommonAce( @@ -676,6 +690,7 @@ public async Task CertAbuseProcessor_CreateEnrollmentAgentRestriction_Unresolved Assert.Null(result.restriction); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task CertAbuseProcessor_CreateEnrollmentAgentRestriction_NoTemplate_ReturnsAllTemplates() { var emptyOpaqueAce = new CommonAce( @@ -709,6 +724,7 @@ public async Task CertAbuseProcessor_CreateEnrollmentAgentRestriction_NoTemplate Assert.Contains(result.restriction.Targets, t => t.ObjectIdentifier == "S-1-3"); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task CertAbuseProcessor_CreateEnrollmentAgentRestriction_WithCanonicalName_ReturnsTemplate() { var expectedPrincipalType = Label.CertTemplate; @@ -742,6 +758,7 @@ public async Task CertAbuseProcessor_CreateEnrollmentAgentRestriction_WithCanoni Times.Once); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task CertAbuseProcessor_CreateEnrollmentAgentRestriction_WithCertTemplateOID_ReturnsTemplate() { var expectedPrincipalType = Label.CertTemplate; diff --git a/test/unit/CommonLibHelperTests.cs b/test/unit/CommonLibHelperTests.cs index f2e4c0c17..20dacc4de 100644 --- a/test/unit/CommonLibHelperTests.cs +++ b/test/unit/CommonLibHelperTests.cs @@ -1,5 +1,5 @@ using System; -using System.Security.Principal; +using System.Runtime.Versioning; using System.Text; using System.Threading.Tasks; using SharpHoundCommonLib; @@ -302,6 +302,7 @@ public void DomainNameToDistinguishedName_DotsBecomeDcComponents() Assert.Equal("DC=test,DC=local", result); } + [SupportedOSPlatform("windows")] [WindowsOnlyTheory] [InlineData("S-1-5-32-544", "\\01\\02\\00\\00\\00\\00\\00\\05\\20\\00\\00\\00\\20\\02\\00\\00")] public void ConvertSidToHexSid_ValidSid_MatchesSecurityIdentifierBinaryForm(string sid, string expectedHexSid) @@ -322,6 +323,7 @@ static string BuildExpectedHexSid(string sid) } } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public void ConvertSidToHexSid_InvalidSid_Throws() { diff --git a/test/unit/DomainTrustProcessorTest.cs b/test/unit/DomainTrustProcessorTest.cs index c5fb3ef80..2ada97fc2 100644 --- a/test/unit/DomainTrustProcessorTest.cs +++ b/test/unit/DomainTrustProcessorTest.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.DirectoryServices.Protocols; using System.Linq; +using System.Runtime.Versioning; using System.Threading; using System.Threading.Tasks; using CommonLibTest.Facades; @@ -23,6 +24,7 @@ public DomainTrustProcessorTest(ITestOutputHelper testOutputHelper) _testOutputHelper = testOutputHelper; } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task DomainTrustProcessor_EnumerateDomainTrusts_HappyPath() { diff --git a/test/unit/GPOLocalGroupProcessorTest.cs b/test/unit/GPOLocalGroupProcessorTest.cs index 4f69ea449..07107a12e 100644 --- a/test/unit/GPOLocalGroupProcessorTest.cs +++ b/test/unit/GPOLocalGroupProcessorTest.cs @@ -3,6 +3,7 @@ using System.DirectoryServices.Protocols; using System.IO; using System.Linq; +using System.Runtime.Versioning; using System.Threading; using System.Threading.Tasks; using CommonLibTest.Facades; @@ -295,6 +296,7 @@ public async Task GPOLocalGroupProcessor_ReadGPOLocalGroups_Does_Not_Skip_Enable Assert.Empty(act3.LocalAdmins); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task GPOLocalGroupProcessor_ReadGPOLocalGroups() { var mockLDAPUtils = new Mock(MockBehavior.Loose); diff --git a/test/unit/GroupProcessorTest.cs b/test/unit/GroupProcessorTest.cs index 2a670bcec..e54d445fa 100644 --- a/test/unit/GroupProcessorTest.cs +++ b/test/unit/GroupProcessorTest.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Runtime.Versioning; using System.Threading; using System.Threading.Tasks; using CommonLibTest.Facades; @@ -53,6 +54,7 @@ public void GroupProcessor_GetPrimaryGroupInfo_NullPrimaryGroupID_ReturnsNull() Assert.Null(result); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public void GroupProcessor_GetPrimaryGroupInfo_ReturnsCorrectSID() { @@ -104,6 +106,7 @@ public async Task GroupProcessor_ReadGroupMembers_EmptyMembers_DoesRangedRetriev Assert.Equal(expected, results); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task GroupProcessor_ReadGroupMembers_ReturnsCorrectMembers() { diff --git a/test/unit/LDAPUtilsTest.cs b/test/unit/LDAPUtilsTest.cs index aa73505be..d6d6514ec 100644 --- a/test/unit/LDAPUtilsTest.cs +++ b/test/unit/LDAPUtilsTest.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.DirectoryServices.ActiveDirectory; +using System.Runtime.Versioning; using System.Threading.Tasks; using CommonLibTest.Facades; using Moq; @@ -258,6 +259,7 @@ public async Task Test_ResolveHostToSid_BlankHost() { Assert.False(success); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task EnterpriseDomainControllersGroup_CorrectValues() { var utilsMock = new Mock(); diff --git a/test/unit/LdapPropertyTests.cs b/test/unit/LdapPropertyTests.cs index 095b1728d..1e5dfccb9 100644 --- a/test/unit/LdapPropertyTests.cs +++ b/test/unit/LdapPropertyTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.DirectoryServices; +using System.Runtime.Versioning; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Security.Principal; @@ -174,6 +175,7 @@ public async Task LDAPPropertyProcessor_ReadGroupProperties_NullAdminCount() Assert.False((bool)test["admincount"]); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task LDAPPropertyProcessor_ReadGroupProperties_Returns_HasSIDHistory() { @@ -300,6 +302,7 @@ public async Task LDAPPropertyProcessor_ReadUserProperties_NullAdminCount() Assert.False((bool)props["admincount"]); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task LDAPPropertyProcessor_ReadUserProperties_HappyPath() { @@ -427,6 +430,7 @@ public async Task LDAPPropertyProcessor_ReadUserProperties_TestBadPaths() Assert.DoesNotContain("trustedtoauth", keys); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task LDAPPropertyProcessor_ReadComputerProperties_HappyPath() { @@ -999,6 +1003,7 @@ public void LDAPPropertyProcessor_ParseAllProperties_CollectionCountOne_ControlC Assert.Equal("\u0000", UTF8.GetString(usercert as byte[])); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public void LDAPPropertyProcessor_ParseAllProperties_CollectionCountOne_SID() { var creatorSIDExpected = "S-1-5-21-2697957641-2271029196-387917394"; @@ -1364,6 +1369,8 @@ public async Task LDAPPropertyProcessor_ReadUserProperties_TestDelegatesNull() }; Assert.Equal(expected, atdr); } + + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task LDAPPropertyProcessor_ReadComputerProperties_TestDelegatesNull() { @@ -1428,6 +1435,7 @@ public async Task LDAPPropertyProcessor_ReadComputerProperties_TestDelegatesNull Assert.Equal("A6F75BA4-F1AE-4B47-A606-E3A0A69AEC83", props["objectguid"]); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task LDAPPropertyProcessor_ReadComputerProperties_AllowedToActOnBehalfOfOtherIdentity() { diff --git a/test/unit/LocalGroupProcessorTest.cs b/test/unit/LocalGroupProcessorTest.cs index 41e54c12a..87ee13205 100644 --- a/test/unit/LocalGroupProcessorTest.cs +++ b/test/unit/LocalGroupProcessorTest.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Versioning; using System.Threading.Tasks; using CommonLibTest.Facades; using Moq; @@ -25,6 +26,7 @@ public LocalGroupProcessorTest(ITestOutputHelper testOutputHelper) { public void Dispose() { } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task LocalGroupProcessor_TestWorkstation() { var mockProcessor = new Mock(new MockLdapUtils(), null); @@ -53,6 +55,7 @@ public async Task LocalGroupProcessor_TestWorkstation() { }); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task LocalGroupProcessor_TestDomainController() { var mockProcessor = new Mock(new MockLdapUtils(), null); @@ -201,6 +204,7 @@ public async Task LocalGroupProcessor_GetLocalGroups_GetMachineSidResultFailed() Assert.Equal("GetMachineSid", status.Task); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task LocalGroupProcessor_GetLocalGroups_GetDomainsResultFailed() { var mockProcessor = new Mock(new MockLdapUtils(), null); @@ -222,6 +226,7 @@ public async Task LocalGroupProcessor_GetLocalGroups_GetDomainsResultFailed() { Assert.Equal("GetDomains", status.Task); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task LocalGroupProcessor_GetLocalGroups_OpenDomainResultFailed() { var mockProcessor = new Mock(new MockLdapUtils(), null); @@ -243,6 +248,7 @@ public async Task LocalGroupProcessor_GetLocalGroups_OpenDomainResultFailed() { Assert.Equal("OpenDomain - BUILTIN", status.Task); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task LocalGroupProcessor_GetLocalGroups_GetAliasesFailed() { var mockProcessor = new Mock(new MockLdapUtils(), null); @@ -264,6 +270,7 @@ public async Task LocalGroupProcessor_GetLocalGroups_GetAliasesFailed() { Assert.Equal("GetAliases - BUILTIN", status.Task); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task LocalGroupProcessor_GetLocalGroups_OpenAliasFailed() { var mockProcessor = new Mock(new MockLdapUtils(), null); @@ -287,6 +294,7 @@ public async Task LocalGroupProcessor_GetLocalGroups_OpenAliasFailed() { Assert.Equal("OpenAlias - Administrators", status.Task); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task LocalGroupProcessor_GetLocalGroups_GetMembersFailed() { var mockProcessor = new Mock(new MockLdapUtils(), null); @@ -310,6 +318,7 @@ public async Task LocalGroupProcessor_GetLocalGroups_GetMembersFailed() { Assert.Equal("GetMembersInAlias - Users", status.Task); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task LocalGroupProcessor_GetLocalGroups_LookupPrincipalBySid() { var mockProcessor = new Mock(new MockLdapUtils(), null); @@ -339,6 +348,7 @@ public async Task LocalGroupProcessor_GetLocalGroups_LookupPrincipalBySid() { }); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task LocalGroupProcessor_GetLocalGroups_PreviouslyCached() { var mockProcessor = new Mock(new MockLdapUtils(), null); diff --git a/test/unit/UserRightsAssignmentProcessorTest.cs b/test/unit/UserRightsAssignmentProcessorTest.cs index 14fbc9f8c..1f1f6a550 100644 --- a/test/unit/UserRightsAssignmentProcessorTest.cs +++ b/test/unit/UserRightsAssignmentProcessorTest.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Versioning; using System.Threading; using System.Threading.Tasks; using CommonLibTest.CollectionDefinitions; @@ -31,6 +32,7 @@ public UserRightsAssignmentProcessorTest(ITestOutputHelper testOutputHelper) Cache.SetCacheInstance(null); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task UserRightsAssignmentProcessor_TestWorkstation() { @@ -53,6 +55,7 @@ public async Task UserRightsAssignmentProcessor_TestWorkstation() Assert.Equal(Label.LocalGroup, rdpResult.ObjectType); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task UserRightsAssignmentProcessor_TestDC() { @@ -96,6 +99,7 @@ public async Task UserRightsAssignmentProcessor_TestDC() // Assert.Equal("Timeout", status.Status); // } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task UserRightsAssignmentProcessor_TestGetLocalDomainInformationFail() { @@ -122,6 +126,7 @@ public async Task UserRightsAssignmentProcessor_TestGetLocalDomainInformationFai Assert.Equal("LSAGetMachineSID", status.Task); } + [SupportedOSPlatform("windows")] [WindowsOnlyFact] public async Task UserRightsAssignmentProcessor_TestGetResolvedPrincipalsWithPrivilegeFail() { diff --git a/test/unit/WebClientServiceProcessorTest.cs b/test/unit/WebClientServiceProcessorTest.cs index 9ea9cd433..d4f5cbe26 100644 --- a/test/unit/WebClientServiceProcessorTest.cs +++ b/test/unit/WebClientServiceProcessorTest.cs @@ -26,7 +26,7 @@ public WebClientServiceProcessorTest(ITestOutputHelper testOutputHelper) { public void Dispose() { } - [WindowsOnlyFact] + [Fact] public async Task WebClientServiceProcessorTest_TestPathExists() { var processor = new WebClientServiceProcessor(); From e223096e0c85b7bec5db4b9435833919252f010b Mon Sep 17 00:00:00 2001 From: Lucas Falslev Date: Thu, 19 Feb 2026 17:01:46 -0700 Subject: [PATCH 2/6] fix NU1701 and suppress NU1702, nuget dependency warnings --- src/CommonLib/SharpHoundCommonLib.csproj | 2 +- test/unit/CommonLibTest.csproj | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CommonLib/SharpHoundCommonLib.csproj b/src/CommonLib/SharpHoundCommonLib.csproj index 820856988..3e973d87c 100644 --- a/src/CommonLib/SharpHoundCommonLib.csproj +++ b/src/CommonLib/SharpHoundCommonLib.csproj @@ -18,7 +18,7 @@ full - + diff --git a/test/unit/CommonLibTest.csproj b/test/unit/CommonLibTest.csproj index cd4ca2f32..601b7b369 100644 --- a/test/unit/CommonLibTest.csproj +++ b/test/unit/CommonLibTest.csproj @@ -6,6 +6,8 @@ true ..\..\docfx\coverage\ OpenCover + //Suppress cross-targeting warning when referencing net472 SharpHound projects in net8.0 tests + $(NoWarn);NU1702 From a2c3f0dc615bac40b2e4440fc045186c0bf72aa6 Mon Sep 17 00:00:00 2001 From: Lucas Falslev Date: Thu, 19 Feb 2026 17:04:59 -0700 Subject: [PATCH 3/6] Other Test Fixes --- src/CommonLib/Logging/Logging.cs | 3 +-- test/unit/CommonLibHelperTests.cs | 9 --------- test/unit/DCLdapProcessorTest.cs | 2 -- .../{MockExtentions.cs => MockExtensions.cs} | 13 +++++++++---- test/unit/LdapPropertyTests.cs | 2 +- 5 files changed, 11 insertions(+), 18 deletions(-) rename test/unit/Facades/{MockExtentions.cs => MockExtensions.cs} (80%) diff --git a/src/CommonLib/Logging/Logging.cs b/src/CommonLib/Logging/Logging.cs index eae08c7ba..cc1715eff 100644 --- a/src/CommonLib/Logging/Logging.cs +++ b/src/CommonLib/Logging/Logging.cs @@ -1,5 +1,4 @@ -#nullable enable -using System.Collections.Concurrent; +using System.Collections.Concurrent; using Microsoft.Extensions.Logging; namespace SharpHoundCommonLib diff --git a/test/unit/CommonLibHelperTests.cs b/test/unit/CommonLibHelperTests.cs index 20dacc4de..8ba4b0ed2 100644 --- a/test/unit/CommonLibHelperTests.cs +++ b/test/unit/CommonLibHelperTests.cs @@ -312,15 +312,6 @@ public void ConvertSidToHexSid_ValidSid_MatchesSecurityIdentifierBinaryForm(stri // Assert Assert.Equal(expectedHexSid, actual); - return; - - static string BuildExpectedHexSid(string sid) - { - var securityIdentifier = new SecurityIdentifier(sid); - var sidBytes = new byte[securityIdentifier.BinaryLength]; - securityIdentifier.GetBinaryForm(sidBytes, 0); - return $"\\{BitConverter.ToString(sidBytes).Replace('-', '\\')}"; - } } [SupportedOSPlatform("windows")] diff --git a/test/unit/DCLdapProcessorTest.cs b/test/unit/DCLdapProcessorTest.cs index 277598652..1b4d9da60 100644 --- a/test/unit/DCLdapProcessorTest.cs +++ b/test/unit/DCLdapProcessorTest.cs @@ -138,7 +138,6 @@ public async Task DCLdapProcessor_CheckIsNtlmSigningRequired_Exception() { [Fact] public async Task DCLdapProcessor_Authenticate_InvalidCredentialsException_SEC_E_UNSUPPORTED_FUNCTION() { - var exception = "ErrorTest"; var endpoint = "http://primary.testlab.local/"; var expected = $"LDAP endpoint '{endpoint}' does not support NTLM"; @@ -153,7 +152,6 @@ public async Task DCLdapProcessor_Authenticate_InvalidCredentialsException_SEC_E [Fact] public async Task DCLdapProcessor_Authenticate_InvalidCredentialsException_SEC_E_BAD_BINDINGS() { - var exception = "ErrorTest"; var endpoint = "http://primary.testlab.local/"; var expected = $"Bad bindings with the LDAPS endpoint '{endpoint}'. Server error: {SEC_E_BAD_BINDINGS}"; diff --git a/test/unit/Facades/MockExtentions.cs b/test/unit/Facades/MockExtensions.cs similarity index 80% rename from test/unit/Facades/MockExtentions.cs rename to test/unit/Facades/MockExtensions.cs index 7d8169e30..8289aabef 100644 --- a/test/unit/Facades/MockExtentions.cs +++ b/test/unit/Facades/MockExtensions.cs @@ -1,3 +1,5 @@ +#nullable enable + using System; using System.Linq; using Microsoft.Extensions.Logging; @@ -5,7 +7,7 @@ namespace CommonLibTest.Facades; -public static class MockExtentions +public static class MockExtensions { public static void VerifyLogContains(this Mock> mockLogger, LogLevel logLevel, params string[] expected) { @@ -13,8 +15,9 @@ public static void VerifyLogContains(this Mock> mockLogger, LogLev x => x.Log( logLevel, It.IsAny(), - It.Is((o, t) => - expected.All(s => o.ToString().Contains(s, StringComparison.OrdinalIgnoreCase))), + It.Is((o, t) => + o != null && + expected.All(s => o.ToString()!.Contains(s, StringComparison.OrdinalIgnoreCase))), It.IsAny(), It.IsAny>()), Times.Once); @@ -32,4 +35,6 @@ public static void VerifyLog(this Mock> mockLogger, LogLevel logLe It.IsAny>()), Times.Once); } -} \ No newline at end of file +} + +#nullable disable \ No newline at end of file diff --git a/test/unit/LdapPropertyTests.cs b/test/unit/LdapPropertyTests.cs index 1e5dfccb9..a1fb9e380 100644 --- a/test/unit/LdapPropertyTests.cs +++ b/test/unit/LdapPropertyTests.cs @@ -1358,7 +1358,7 @@ public async Task LDAPPropertyProcessor_ReadUserProperties_TestDelegatesNull() Assert.Contains("rdpman/win10", atd); var atdr = test.AllowedToDelegate; - Assert.Equal(1, atdr.Length); + Assert.Single(atdr); var expected = new TypedPrincipal[] { new() From 53d8222276313f0686f5dc1df0401157d981b5b9 Mon Sep 17 00:00:00 2001 From: Lucas Falslev Date: Thu, 19 Feb 2026 17:05:27 -0700 Subject: [PATCH 4/6] SYSLIB0050 - replace deprecated call --- test/unit/Facades/FacadeHelpers.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/unit/Facades/FacadeHelpers.cs b/test/unit/Facades/FacadeHelpers.cs index 2b097e8be..619d7e255 100644 --- a/test/unit/Facades/FacadeHelpers.cs +++ b/test/unit/Facades/FacadeHelpers.cs @@ -1,5 +1,5 @@ using System.Reflection; -using System.Runtime.Serialization; +using System.Runtime.CompilerServices; namespace CommonLibTest.Facades { @@ -9,8 +9,8 @@ public class FacadeHelpers private const BindingFlags publicInstance = BindingFlags.Public | BindingFlags.Instance; internal static T GetUninitializedObject() - { - return (T) FormatterServices.GetUninitializedObject(typeof(T)); + { + return (T)RuntimeHelpers.GetUninitializedObject(typeof(T)); } internal static void SetField(T1 obj, string propertyName, T2 propertyValue) From f90a0c1fee353b35333a37b29b7a121d5f231466 Mon Sep 17 00:00:00 2001 From: Lucas Falslev Date: Thu, 19 Feb 2026 17:06:50 -0700 Subject: [PATCH 5/6] fix comment syntax --- test/unit/CommonLibTest.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/CommonLibTest.csproj b/test/unit/CommonLibTest.csproj index 601b7b369..df2ac7259 100644 --- a/test/unit/CommonLibTest.csproj +++ b/test/unit/CommonLibTest.csproj @@ -6,7 +6,7 @@ true ..\..\docfx\coverage\ OpenCover - //Suppress cross-targeting warning when referencing net472 SharpHound projects in net8.0 tests + $(NoWarn);NU1702 From a705a68998872d3652fde37d235c2696885d5ad5 Mon Sep 17 00:00:00 2001 From: Lucas Falslev Date: Thu, 19 Feb 2026 17:23:56 -0700 Subject: [PATCH 6/6] enable nullable context --- src/CommonLib/Ntlm/LdapTransport.cs | 7 +++++-- src/CommonLib/Processors/DCLdapProcessor.cs | 14 +++++++++----- src/CommonLib/SMB/NetBIOS/NetBIOSSessionType.cs | 6 +++++- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/CommonLib/Ntlm/LdapTransport.cs b/src/CommonLib/Ntlm/LdapTransport.cs index 04ba8c73a..e5652ca9c 100644 --- a/src/CommonLib/Ntlm/LdapTransport.cs +++ b/src/CommonLib/Ntlm/LdapTransport.cs @@ -1,4 +1,5 @@ - +#nullable enable + using Microsoft.Extensions.Logging; using SharpHoundCommonLib.Enums; using System; @@ -85,4 +86,6 @@ public void Dispose() { _disposed = true; } } -} \ No newline at end of file +} + +#nullable disable \ No newline at end of file diff --git a/src/CommonLib/Processors/DCLdapProcessor.cs b/src/CommonLib/Processors/DCLdapProcessor.cs index d23639f4c..c0fb09974 100644 --- a/src/CommonLib/Processors/DCLdapProcessor.cs +++ b/src/CommonLib/Processors/DCLdapProcessor.cs @@ -1,4 +1,6 @@ -using Microsoft.Extensions.Logging; +#nullable enable + +using Microsoft.Extensions.Logging; using SharpHoundCommonLib.Enums; using SharpHoundCommonLib.Ntlm; using SharpHoundCommonLib.OutputTypes; @@ -33,7 +35,7 @@ public class DCLdapProcessor { private readonly string SEC_E_BAD_BINDINGS = "80090346"; - public DCLdapProcessor(int connectionTimeoutMs, string dcHostname, ILogger log = null) { + public DCLdapProcessor(int connectionTimeoutMs, string dcHostname, ILogger? log = null) { _log = log ?? Logging.LogProvider.CreateLogger("DCLdapProcessor"); _scanner = new PortScanner(maxTimeout: connectionTimeoutMs); _ldapTimeout = connectionTimeoutMs / 1000; @@ -43,7 +45,7 @@ public DCLdapProcessor(int connectionTimeoutMs, string dcHostname, ILogger log = _checkIsChannelBindingDisabledAdaptiveTimeout = new AdaptiveTimeout(maxTimeout: TimeSpan.FromMinutes(1), Logging.LogProvider.CreateLogger(nameof(CheckIsChannelBindingDisabled))); } - public event ComputerStatusDelegate ComputerStatusEvent; + public event ComputerStatusDelegate? ComputerStatusEvent; public async Task Scan(string computerName, string computerObjectId) { var hasLdap = await TestLdapPort(); @@ -173,7 +175,7 @@ public virtual async Task TestLdapsPort() { /// /// /// - protected internal virtual async Task Authenticate(Uri endpoint, LdapAuthOptions options, NtlmAuthenticationHandler ntlmAuth = null, LdapTransport ldapTransport = null, CancellationToken cancellationToken = default) { + protected internal virtual async Task Authenticate(Uri endpoint, LdapAuthOptions options, NtlmAuthenticationHandler? ntlmAuth = null, LdapTransport? ldapTransport = null, CancellationToken cancellationToken = default) { var host = endpoint.Host; var auth = ntlmAuth ?? new NtlmAuthenticationHandler($"LDAP/{host.ToUpper()}") { Options = options @@ -229,4 +231,6 @@ protected internal virtual async Task Authenticate(Uri endpoint, LdapAuthO private async Task SendComputerStatus(CSVComputerStatus status) { if (ComputerStatusEvent is not null) await ComputerStatusEvent.Invoke(status); } -} \ No newline at end of file +} + +#nullable disable \ No newline at end of file diff --git a/src/CommonLib/SMB/NetBIOS/NetBIOSSessionType.cs b/src/CommonLib/SMB/NetBIOS/NetBIOSSessionType.cs index 63e09ac89..1c35afcd3 100644 --- a/src/CommonLib/SMB/NetBIOS/NetBIOSSessionType.cs +++ b/src/CommonLib/SMB/NetBIOS/NetBIOSSessionType.cs @@ -1,4 +1,6 @@ -using System; +#nullable enable + +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -127,3 +129,5 @@ public override bool Equals(object? obj) => !(left == right); } } + +#nullable disable \ No newline at end of file