├── src ├── Plugins │ ├── AzureDevOpsConfiguration │ │ ├── AdoPat.txt │ │ ├── build │ │ │ └── Sarif.PatternMatcher.AzureDevOpsConfiguration.targets │ │ ├── AzureDevOpsConfiguration.SharedStrings.txt │ │ └── AZC101.BuildDefinitionSecurity.json │ ├── Tests.Security │ │ ├── TestData │ │ │ ├── SecurePlaintextSecrets │ │ │ │ ├── Inputs │ │ │ │ │ ├── SEC101_047.CratesApiKey.ps1 │ │ │ │ │ ├── SEC101_003.GoogleApiKey.txt │ │ │ │ │ ├── SEC101_031.NuGetApiKey.txt │ │ │ │ │ ├── SEC101_025.SendGridApiKey.txt │ │ │ │ │ ├── SEC101_014.FacebookAccessToken.ps1 │ │ │ │ │ ├── SEC101_024.TwilioApiKey.ps1 │ │ │ │ │ ├── SEC101_049.TelegramBotToken.ps1 │ │ │ │ │ ├── SEC101_012.SlackWebhook.txt │ │ │ │ │ ├── SEC101_019.PicaticApiKey.ps1 │ │ │ │ │ ├── SEC101_040.ShopifySharedSecret.ps1 │ │ │ │ │ ├── SEC101_017.NpmLegacyAuthorToken.ps1 │ │ │ │ │ ├── SEC101_027.MailChimpApiKey.ps1 │ │ │ │ │ ├── SEC101_005.SlackApiKey.py │ │ │ │ │ ├── SEC101_039.ShopifyAccessToken.ps1 │ │ │ │ │ ├── SEC101_022.PayPalBraintreeAccessToken.ps1 │ │ │ │ │ ├── SEC101_045.PostmanApiKey.ps1 │ │ │ │ │ ├── SEC101_021.DropboxAppCredentials.ps1 │ │ │ │ │ ├── SEC101_042.DynatraceToken.ps1 │ │ │ │ │ ├── SEC101_050.NpmIdentifiableAuthorToken.ps1 │ │ │ │ │ ├── SEC101_016.StripeApiKey.txt │ │ │ │ │ ├── SEC101_051.StripeTestApiKey.txt │ │ │ │ │ ├── SEC101_048.SlackWorkflowKey.ps1 │ │ │ │ │ ├── SEC101_052.StripeLiveRestrictedApiKey.txt │ │ │ │ │ ├── SEC101_053.StripeTestRestrictedApiKey.txt │ │ │ │ │ ├── SEC101_018.TwilioCredentials.ps1 │ │ │ │ │ ├── SEC101_020.DropboxAccessToken.ps1 │ │ │ │ │ ├── SEC101_046.DiscordApiCredentials.ps1 │ │ │ │ │ ├── SEC101_010.SquarePat.ps1 │ │ │ │ │ ├── SEC101_009.LinkedInCredentials.ps1 │ │ │ │ │ ├── SEC101_002.GoogleOAuthCredentials.ps1 │ │ │ │ │ ├── SEC101_011.SquareCredentials.ps1 │ │ │ │ │ ├── SEC101_007.GitHubAppCredentials.ps1 │ │ │ │ │ ├── SEC101_026.MailgunApiCredentials.ps1 │ │ │ │ │ ├── SEC101_034.CredentialObject.ps1 │ │ │ │ │ ├── SEC101_102.AdoPat.txt │ │ │ │ │ ├── SEC101_035.CloudantCredentials.ps1 │ │ │ │ │ ├── SEC101_032.GpgCredentials.ps1 │ │ │ │ │ ├── SEC101_004.FacebookAppCredentials.ps1 │ │ │ │ │ ├── SEC101_033.MongoDbCredentials.ps1 │ │ │ │ │ ├── SEC101_029.AlibabaCloudCredentials.ps1 │ │ │ │ │ ├── SEC101_041.RabbitMqCredentials.ps1 │ │ │ │ │ ├── SEC101_015.AkamaiCredentials.ps1 │ │ │ │ │ ├── SEC101_008.AwsCredentials.ps1 │ │ │ │ │ ├── SEC101_006.GitHubLegacyPat.ps1 │ │ │ │ │ ├── SEC101_030.GoogleServiceAccountKey.ps1 │ │ │ │ │ ├── SEC101_001.HttpAuthorizationRequestHeader.ps1 │ │ │ │ │ └── SEC101_043.NuGetCredentials.ps1 │ │ │ │ └── ExpectedOutputs │ │ │ │ │ ├── SEC101_047.CratesApiKey.sarif │ │ │ │ │ └── SEC101_001.HttpAuthorizationRequestHeader.sarif │ │ │ ├── ReviewPotentiallySensitiveData │ │ │ │ └── Inputs │ │ │ │ │ ├── SEC102_003.Url.ps1 │ │ │ │ │ └── SEC102_002.SocialSecurityNumber.txt │ │ │ ├── ReviewPotentiallySensitiveFiles │ │ │ │ └── Inputs │ │ │ │ │ ├── SEC103_004.CertificateFile_der_encoded.cer │ │ │ │ │ ├── SEC103_024.MicrosoftSerializedCertificateStoreFile_default.sst │ │ │ │ │ └── SEC103_002.ASCIIArmoredFile_fake.asc │ │ │ ├── EmptyResults.sarif │ │ │ └── UseSecureApi │ │ │ │ └── Inputs │ │ │ │ ├── SEC104.Memory.Allocation_malloca.c │ │ │ │ └── SEC104.Memory.Allocation_alloca.c │ │ ├── xunit.runner.json │ │ ├── SEC104.UseSecureApiTests.cs │ │ ├── SEC102.ReviewPotentiallySensitiveDataTests.cs │ │ ├── SEC103.ReviewPotentiallySensitiveFilesTests.cs │ │ ├── SEC101.SecurePlaintextSecretsTests.cs │ │ ├── SecurePlaintextSecretsValidators │ │ │ ├── SEC101_036.MySqlCredentialsValidatorTests.cs │ │ │ └── SEC101_037.SqlCredentialsValidatorTests.cs │ │ ├── ValidatorBaseTests.cs │ │ └── Tests.Security.csproj │ ├── Security │ │ ├── SecurePlaintextSecretsValidators │ │ │ ├── SEC101_016.StripeApiKeyValidator.cs │ │ │ ├── SEC101_051.StripeTestApiKeyValidator.cs │ │ │ ├── SEC101_052.StripeLiveRestrictedKeyValidator.cs │ │ │ ├── SEC101_053.StripeTestRestrictedApiKeyValidator.cs │ │ │ ├── SEC101_031.NuGetApiKeyValidator.cs │ │ │ ├── SEC101_024.TwilioApiKeyValidator.cs │ │ │ ├── SEC101_019.PicaticApiKeyValidator.cs │ │ │ ├── SEC101_023.AmazonMwsAuthTokenValidator.cs │ │ │ ├── SEC101_042.DynatraceTokenValidator.cs │ │ │ ├── SEC101_039.ShopifyAccessTokenValidator.cs │ │ │ ├── SEC101_040.ShopifySharedSecretValidator.cs │ │ │ ├── SEC101_014.FacebookAccessTokenValidator.cs │ │ │ ├── SEC101_022.PayPalBraintreeAccessTokenValidator.cs │ │ │ ├── SEC101_032.GpgCredentialsValidator.cs │ │ │ ├── SEC101_030.GoogleServiceAccountKeyValidator.cs │ │ │ ├── SEC101_028.PlaintextPasswordValidator.cs │ │ │ ├── SEC101_047.CratesApiKeyValidator.cs │ │ │ ├── SEC101_034.CredentialObjectValidator.cs │ │ │ ├── SEC101_002.GoogleOAuthCredentialsValidator.cs │ │ │ ├── SEC101_009.LinkedInCredentialsValidator.cs │ │ │ └── SEC101_017.NpmLegacyAuthorTokenValidator.cs │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ ├── Utilities │ │ │ ├── DictionaryExtensions.cs │ │ │ └── FilteringHelpers.cs │ │ ├── build │ │ │ └── Sarif.PatternMatcher.Security.targets │ │ ├── SEC102_003.UrlValidator.cs │ │ ├── ReviewPotentiallySensitiveFilesValidators │ │ │ └── SEC103_024.MicrosoftSerializedCertificateStoreFileValidator.cs │ │ ├── ReviewPotentiallySensitiveDataValidators │ │ │ └── SEC102_001.EmailAddressValidator.cs │ │ └── SEC102.ReviewPotentiallySensitiveData.json │ ├── Utilities.cs │ ├── Tests.SalModernization │ │ ├── TestData │ │ │ └── UpdateSalToCurrentVersion │ │ │ │ └── Inputs │ │ │ │ └── SEC105_001.AnalysisAssume.cpp │ │ ├── EndToEndTestsSalModernization.cs │ │ ├── SEC105.UpdateSalToCurrentVersion.cs │ │ └── Tests.SalModernization.csproj │ ├── Tests.AzureDevOpsConfiguration │ │ ├── EndToEndTestsAzureDevOpsConfiguration.cs │ │ ├── AZC101.BuildDefinitionSecurityTests.cs │ │ ├── AZC102.ServiceConnectionSecurityTests.cs │ │ ├── TestData │ │ │ └── BuildDefinitionSecurity │ │ │ │ └── ExpectedOutputs │ │ │ │ └── AZC101.builddefinition.NoIssue.sarif │ │ └── Tests.AzureDevOpsConfiguration.csproj │ └── SalModernization │ │ ├── build │ │ └── Sarif.PatternMatcher.SalModernization.targets │ │ └── SalModernization.csproj ├── Test.UnitTests.Sarif.PatternMatcher.Cli │ ├── SharedStrings.txt │ ├── SimplePatterns.json │ ├── TestValidators │ │ ├── StaticValidatorExistsForMatchExpressionValidator.cs │ │ └── StaticAndDynamicValidatorsExistForMatchExpressionValidator.cs │ ├── ExportRulesMetatadaCommandTests.cs │ └── Test.UnitTests.Sarif.PatternMatcher.Cli.csproj ├── .sarif │ └── README.txt ├── Sarif.PatternMatcher.Function │ ├── local.settings.json │ ├── host.json │ ├── Properties │ │ ├── serviceDependencies.json │ │ └── serviceDependencies.local.json │ └── FunctionConstants.cs ├── RE2.Native │ ├── stdafx.cpp │ ├── targetver.h │ ├── GroupNameHeader.h │ ├── Submatch.h │ ├── stdafx.h │ ├── Match2.h │ ├── String8.h │ ├── MatchesCaptureGroupsOutput.h │ ├── CMake.Original │ │ └── README.txt │ ├── RE2.Native.vcxproj.filters │ └── ReadMe.txt ├── Sarif.PatternMatcher │ ├── RegexEngine.cs │ ├── ValidationMethods.cs │ ├── Base64EncodingMatch.cs │ ├── SearchDefinitions.cs │ ├── ValidateOptions.cs │ ├── RegexMetadata.cs │ ├── SimpleFix.cs │ ├── SearchDefinition.cs │ ├── SpamEventNames.cs │ ├── SpamExtensionMethods.cs │ ├── Sarif.PatternMatcher.csproj │ ├── AnalyzeOptions.cs │ └── MatchExpression.cs ├── RE2.Managed │ ├── Submatch.cs │ ├── GroupNameHeader.cs │ ├── RegexDefaults.cs │ ├── Match2.cs │ ├── FlexMatch.cs │ ├── MatchesCaptureGroupsOutput.cs │ ├── RE2.Managed.targets │ ├── String8Interop.cs │ ├── FlexMatchValueComparer.cs │ └── RE2.LICENSE.txt ├── Sarif.PatternMatcher.Cli │ ├── DatabaseReaders │ │ └── IDatabaseReader.cs │ ├── Models │ │ ├── ContentSearchPatterns.cs │ │ ├── ArrayOfContentSearcher.cs │ │ └── ContentSearcher.cs │ ├── Enums │ │ └── ConnectionType.cs │ ├── App.config │ ├── ExportConfigurationCommand.cs │ ├── ExportRulesMetatadaOptions.cs │ ├── ImportAndAnalyzeOptions.cs │ ├── ExportSearchDefinitionsOptions.cs │ ├── AnalyzeDatabaseOptions.cs │ └── Sarif.PatternMatcher.Cli.csproj ├── Sarif.PatternMatcher.Benchmark │ ├── Program.cs │ └── Sarif.PatternMatcher.Benchmark.csproj ├── Sarif.PatternMatcher.Sdk │ ├── ValidatorDescriptorAttribute.cs │ ├── FingerprintElements.cs │ ├── Sarif.PatternMatcher.Sdk.csproj │ ├── ValidationResult.cs │ ├── SharedUtilities.cs │ ├── ValidationState.cs │ └── DynamicValidatorBase.cs ├── Test.UnitTests.Sarif.PatternMatcher.Function │ ├── TestLogger.cs │ ├── Test.UnitTests.Sarif.PatternMatcher.Function.csproj │ └── TestHelper.cs ├── Test.UnitTests.Sarif.PatternMatcher │ ├── TestAnalyzeCommand.cs │ ├── BadlyBehavedRule.cs │ ├── Test.UnitTests.Sarif.PatternMatcher.csproj │ ├── TestLogger.cs │ └── TestRuleValidator.cs ├── stylecop.json ├── Strings.Interop │ └── Strings.Interop.csproj ├── Test.UnitTests.Strings.Interop │ ├── Test.UnitTests.Strings.Interop.csproj │ └── FlexStringTests.cs ├── .ruleset ├── Test.UnitTests.RE2.Managed │ ├── FlexMatchTests.cs │ ├── Test.UnitTests.RE2.Managed.csproj │ └── FlexMatchValueComparerTests.cs └── Test.UnitTests.Sarif.PatternMatcher.Sdk │ └── Test.UnitTests.Sarif.PatternMatcher.Sdk.csproj ├── targets ├── Key.snk ├── build.plugins.props ├── build.app.props ├── build.lib.props └── build.test.props ├── docs └── DebugBuild.png ├── BuildAndTest.cmd ├── refs └── runtimes │ ├── win-x64 │ └── native │ │ ├── RE2.Native.x64.dll │ │ └── RE2.Native.x64.pdb │ └── win-x86 │ └── native │ ├── RE2.Native.x86.dll │ └── RE2.Native.x86.pdb ├── .github ├── CODEOWNERS ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── dotnet-format.yml │ └── codeql-analysis.yml ├── .gitmodules ├── version.json ├── scripts ├── ProcessCodeCoverage.ps1 └── BuildPackages.ps1 ├── LICENSE ├── azure-pipelines.yml └── CONTRIBUTING.md /src/Plugins/AzureDevOpsConfiguration/AdoPat.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /targets/Key.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sarif-pattern-matcher/HEAD/targets/Key.snk -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher.Cli/SharedStrings.txt: -------------------------------------------------------------------------------- 1 | $MultipartRegexesId=(x|y)?(?Pid[0-9]) -------------------------------------------------------------------------------- /docs/DebugBuild.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sarif-pattern-matcher/HEAD/docs/DebugBuild.png -------------------------------------------------------------------------------- /BuildAndTest.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | powershell -ExecutionPolicy RemoteSigned -File %~dp0\scripts\BuildAndTest.ps1 %* 3 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_047.CratesApiKey.ps1: -------------------------------------------------------------------------------- 1 | ciodeaddeaddead123412341234dead1234 -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_003.GoogleApiKey.txt: -------------------------------------------------------------------------------- 1 | AIza0deadbeef00deadbeef00deadbeef00dead -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_031.NuGetApiKey.txt: -------------------------------------------------------------------------------- 1 | oy2adeadbeef0deadbeaf00deadbeefedeadbee50deada -------------------------------------------------------------------------------- /refs/runtimes/win-x64/native/RE2.Native.x64.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sarif-pattern-matcher/HEAD/refs/runtimes/win-x64/native/RE2.Native.x64.dll -------------------------------------------------------------------------------- /refs/runtimes/win-x64/native/RE2.Native.x64.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sarif-pattern-matcher/HEAD/refs/runtimes/win-x64/native/RE2.Native.x64.pdb -------------------------------------------------------------------------------- /refs/runtimes/win-x86/native/RE2.Native.x86.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sarif-pattern-matcher/HEAD/refs/runtimes/win-x86/native/RE2.Native.x86.dll -------------------------------------------------------------------------------- /refs/runtimes/win-x86/native/RE2.Native.x86.pdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sarif-pattern-matcher/HEAD/refs/runtimes/win-x86/native/RE2.Native.x86.pdb -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_025.SendGridApiKey.txt: -------------------------------------------------------------------------------- 1 | SG.0deadbeef0deadbeef0dea.deadbeef0deadbeef0deadbeef0deadbeef0deadbee -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_014.FacebookAccessToken.ps1: -------------------------------------------------------------------------------- 1 | "EAACEdEose0cBAtestjunk111111" 2 | 3 | >EAACEdEose0cBAtestjunk22222222< -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_024.TwilioApiKey.ps1: -------------------------------------------------------------------------------- 1 | SK11111111110123456789012345678901 2 | 3 | "SK22222222220123456789012345678901" -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_049.TelegramBotToken.ps1: -------------------------------------------------------------------------------- 1 | https://api.telegram.org/bot123456:AAC-DEF1234ghIkl-zyx57W2v1u123ew11/getMe 2 | -------------------------------------------------------------------------------- /targets/build.plugins.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.1;net472 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_012.SlackWebhook.txt: -------------------------------------------------------------------------------- 1 | https://hooks.slack.com/services/T01JYS3KLKU/B0123456789/deedbeefdeaffeeddeadbeef 2 | -------------------------------------------------------------------------------- /src/.sarif/README.txt: -------------------------------------------------------------------------------- 1 | The solution RE2.Native.sln needs this directory to generate the SARIF files when 2 | building in debug mode. If the folder does not exist, an exception will occur. -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_019.PicaticApiKey.ps1: -------------------------------------------------------------------------------- 1 | sk_test_01234567890123456789012345678901 2 | 3 | sk_live_01234567890123456789012345678901 -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_040.ShopifySharedSecret.ps1: -------------------------------------------------------------------------------- 1 | shpss_11111111110123456789012345678901 2 | 3 | "shpss_22222222220123456789012345678901" -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_017.NpmLegacyAuthorToken.ps1: -------------------------------------------------------------------------------- 1 | npm: "338a0fd3-7378-4ce1-8432-bbfc0f6777ca" 2 | 3 | 338a0fd3-7378-4ce1-8432-bbfc0f6777cb -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_027.MailChimpApiKey.ps1: -------------------------------------------------------------------------------- 1 | 11111111110123456789012345678901-us012345678901 2 | 3 | "22222222220123456789012345678901-us012345678901" -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_005.SlackApiKey.py: -------------------------------------------------------------------------------- 1 | xoxb-83112120353-1016171244646-sGMxuWapBw3w3qdK6OfTjORe 2 | dead-83112120353-1016171244646-sGMxuWapBw3w3qdK6OfTjORf -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/ReviewPotentiallySensitiveData/Inputs/SEC102_003.Url.ps1: -------------------------------------------------------------------------------- 1 | https://msn.com/test 2 | https://msn.com/test/ 3 | https://msn.com/test?foo=bar 4 | https://msn.com/test?foo=bar#bookmark -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Function/local.settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "IsEncrypted": false, 3 | "Values": { 4 | "AzureWebJobsStorage": "UseDevelopmentStorage=true", 5 | "FUNCTIONS_WORKER_RUNTIME": "dotnet" 6 | } 7 | } -------------------------------------------------------------------------------- /targets/build.app.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | net6.0 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/ReviewPotentiallySensitiveData/Inputs/SEC102_002.SocialSecurityNumber.txt: -------------------------------------------------------------------------------- 1 | // These are valid patterns. 2 | 123-45-6789 3 | 4 | // These are not. 5 | 111-45-6789 6 | 123-44-6789 7 | 123-45-6666 -------------------------------------------------------------------------------- /targets/build.lib.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | netstandard2.0 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Code owners file. 2 | # This file controls who is tagged for review for any given pull request. 3 | 4 | # For anything not explicitly taken by someone else: 5 | * @cfaucon @hulonjenkins @michaelcfanning @suvamM 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Src/RE2.Native/re2"] 2 | path = src/RE2.Native/re2 3 | url = https://github.com/google/re2.git 4 | [submodule "Src/sarif-sdk"] 5 | path = src/sarif-sdk 6 | url = https://github.com/microsoft/sarif-sdk 7 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_039.ShopifyAccessToken.ps1: -------------------------------------------------------------------------------- 1 | shpat_11111111110123456789012345678901 2 | 3 | "shpca_22222222220123456789012345678901" 4 | 5 | >shppa_33333333330123456789012345678901< -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_022.PayPalBraintreeAccessToken.ps1: -------------------------------------------------------------------------------- 1 | access_token$production$1111111111012345$01234567890123456789012345678901 2 | 3 | access_token$production$2222222222012345$01234567890123456789012345678901 -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_045.PostmanApiKey.ps1: -------------------------------------------------------------------------------- 1 | #valid credential 2 | PMAK-dead0000dead11113c1e4064-92f00edbc2d214a356c39a3dd537ad1921 3 | 4 | #invalid credential 5 | PMAK-aaaabbbbccccddddeeeeffff-aaaabbbbccccddddeeeeffffggggghhhhi -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_021.DropboxAppCredentials.ps1: -------------------------------------------------------------------------------- 1 | #Valid Pair 2 | dropboxKey: g09uoc368gvgt7h 3 | dropboxSecret: sf05okpc1xd6b18 4 | 5 | #Invalid Pair (Secret is all numbers) 6 | dropboxKey: g09uoc368gvgt7h 7 | dropboxSecret: 111111111111111 -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Changes 2 | 3 | Please provide a brief description of the changes here. 4 | 5 | For significant contributions please make sure you have completed the following items: 6 | 7 | * [ ] `ReleaseHistory.md` updated for non-trivial changes 8 | * [ ] Added unit tests 9 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/ReviewPotentiallySensitiveFiles/Inputs/SEC103_004.CertificateFile_der_encoded.cer: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sarif-pattern-matcher/HEAD/src/Plugins/Tests.Security/TestData/ReviewPotentiallySensitiveFiles/Inputs/SEC103_004.CertificateFile_der_encoded.cer -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_042.DynatraceToken.ps1: -------------------------------------------------------------------------------- 1 | dt0a11.111111111101234567890123.0123456789012345678901234567890123456789012345678901234567890123 2 | 3 | "dt0a11.222222222201234567890123.0123456789012345678901234567890123456789012345678901234567890123" -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_050.NpmIdentifiableAuthorToken.ps1: -------------------------------------------------------------------------------- 1 | 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 2 | 3 | "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" 4 | 5 | # Matches the regex but invalid checksum. 6 | "npm_0dead12Test345DeadTest6789test399Wq8" 7 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_016.StripeApiKey.txt: -------------------------------------------------------------------------------- 1 | 2 | sk_live_0deadbeef0deadbeef0deadb 3 | 4 | sk_live_0deadbeef0deadbeef0deadbeef0deadbe 5 | 6 | sk_live_0deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef0 7 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_051.StripeTestApiKey.txt: -------------------------------------------------------------------------------- 1 | 2 | sk_test_0deadbeef0deadbeef0deadb 3 | 4 | sk_test_0deadbeef0deadbeef0deadbeef0deadbe 5 | 6 | sk_test_0deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef0 7 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_048.SlackWorkflowKey.ps1: -------------------------------------------------------------------------------- 1 | https://hooks.slack.com/workflows/0123456789/0123456789/0123456789/01234567890123456789dead 2 | 3 | # Invalid secret 4 | https://hooks.slack.com/workflows/0123456789/0123456789/0123456789/012345678901234567890000 -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_052.StripeLiveRestrictedApiKey.txt: -------------------------------------------------------------------------------- 1 | 2 | rk_live_0deadbeef0deadbeef0deadb 3 | 4 | rk_live_0deadbeef0deadbeef0deadbeef0deadbe 5 | 6 | rk_live_0deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef0 7 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_053.StripeTestRestrictedApiKey.txt: -------------------------------------------------------------------------------- 1 | 2 | rk_test_0deadbeef0deadbeef0deadb 3 | 4 | rk_test_0deadbeef0deadbeef0deadbeef0deadbe 5 | 6 | rk_test_0deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef00deadebeef0 7 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Function/host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "logging": { 4 | "applicationInsights": { 5 | "samplingExcludedTypes": "Request", 6 | "samplingSettings": { 7 | "isEnabled": true 8 | } 9 | } 10 | } 11 | } -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_018.TwilioCredentials.ps1: -------------------------------------------------------------------------------- 1 | var twilioId = "AC11111111111111111111111111111111"; 2 | var twilioKey = "c9117d87046fc24205e4240e6bc9963a"; 3 | 4 | AC11111111111111111111111111111112>/twilioId> 5 | c9117d87046fc24205e4240e6bc9963a 6 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/ReviewPotentiallySensitiveFiles/Inputs/SEC103_024.MicrosoftSerializedCertificateStoreFile_default.sst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sarif-pattern-matcher/HEAD/src/Plugins/Tests.Security/TestData/ReviewPotentiallySensitiveFiles/Inputs/SEC103_024.MicrosoftSerializedCertificateStoreFile_default.sst -------------------------------------------------------------------------------- /src/RE2.Native/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // $safeprojectname$.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Function/Properties/serviceDependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "appInsights1": { 4 | "type": "appInsights" 5 | }, 6 | "secrets1": { 7 | "type": "secrets" 8 | }, 9 | "storage1": { 10 | "type": "storage", 11 | "connectionId": "AzureWebJobsStorage" 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/RE2.Native/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_020.DropboxAccessToken.ps1: -------------------------------------------------------------------------------- 1 | # No expiration 2 | dropbox: 3g2u1OFlqngAAAAAAAAAARsJBUfljyXkQImmVaieedYBk9VlSGxEP_N6V84qPoZ4 3 | 4 | # Short expiration 5 | dropbox: sl.AtS80GLHpwtH4xnmVKHE_odL4vp3m_3RVO_eH0Swdj3QkyFNBIV0kmb3jdDdzz-EwrZ9HiJO3gIKMCF3ovbf-MG6z5DVEFgfI8jzet2F5tze_bmdCeZJzsDPBKRSV9gxOi3JMS8 -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_046.DiscordApiCredentials.ps1: -------------------------------------------------------------------------------- 1 | # ************ Below caught in $SEC101/046.DiscordApiCredentials 2 | 3 | 4 | # AppSettings style 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /version.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", 3 | "version": "4.6.0", 4 | "publicReleaseRefSpec": [ 5 | "^refs/heads/main$", 6 | "^refs/heads/release/v\\d+\\.\\d+\\.\\d+$" 7 | ], 8 | "release": { 9 | "branchName": "release/v{version}" 10 | } 11 | } -------------------------------------------------------------------------------- /src/RE2.Native/GroupNameHeader.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #pragma once 5 | #pragma pack(push, 1) 6 | 7 | #include 8 | 9 | struct alignas(1) GroupNameHeader { 10 | int32_t Index; 11 | int32_t Length; 12 | }; 13 | 14 | #pragma pack(pop) 15 | -------------------------------------------------------------------------------- /src/RE2.Native/Submatch.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // Copyright (c) Microsoft. All rights reserved. 3 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 4 | 5 | #pragma once 6 | #pragma pack(push, 1) 7 | 8 | #include 9 | 10 | struct alignas(1) Submatch { 11 | int32_t Index; 12 | int32_t Length; 13 | }; 14 | 15 | #pragma pack(pop) 16 | -------------------------------------------------------------------------------- /src/RE2.Native/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #include 11 | #include 12 | 13 | 14 | 15 | // TODO: reference additional headers your program requires here 16 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_010.SquarePat.ps1: -------------------------------------------------------------------------------- 1 | # Code style 2 | var square = "EAAAEBpgJyJZkHNhmvmIzc2jPU4fnuYzw3LmTy-ch0fhmFnmLt_faEIS_5i81671"; 3 | 4 | # Json style 5 | { 6 | "square": "EAAAEBpgJyJZkHNhmvmIzc2jPU4fnuYzw3LmTy-ch0fhmFnmLt_faEIS_5i81672" 7 | } 8 | 9 | # Xml style 10 | EAAAEBpgJyJZkHNhmvmIzc2jPU4fnuYzw3LmTy-ch0fhmFnmLt_faEIS_5i81673 11 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/EmptyResults.sarif: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.4.json", 3 | "version": "2.1.0", 4 | "runs": [ 5 | { 6 | "tool": { 7 | "driver": { 8 | "name": "Shell file for initializing tests." 9 | } 10 | }, 11 | "results": [], 12 | "columnKind": "utf16CodeUnits" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher/RegexEngine.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 5 | { 6 | public enum RegexEngine 7 | { 8 | None, 9 | DotNet, 10 | CachedDotNet, 11 | RE2, 12 | IronRE2, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Function/Properties/serviceDependencies.local.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "appInsights1": { 4 | "type": "appInsights.sdk" 5 | }, 6 | "secrets1": { 7 | "type": "secrets.user" 8 | }, 9 | "storage1": { 10 | "resourceId": null, 11 | "type": "storage.emulator", 12 | "connectionId": "AzureWebJobsStorage", 13 | "secretStore": "LocalSecretsFile" 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /.github/workflows/dotnet-format.yml: -------------------------------------------------------------------------------- 1 | name: dotnet format 2 | 3 | on: 4 | pull_request: 5 | branches: [ main ] 6 | 7 | jobs: 8 | check-format: 9 | runs-on: windows-latest 10 | 11 | steps: 12 | - name: check out code 13 | uses: actions/checkout@v2 14 | 15 | - name: Install format tool 16 | run: dotnet tool install -g dotnet-format 17 | 18 | - name: dotnet format 19 | run: dotnet-format --folder --check 20 | -------------------------------------------------------------------------------- /scripts/ProcessCodeCoverage.ps1: -------------------------------------------------------------------------------- 1 | nuget install Microsoft.CodeCoverage -version 16.10.0 2 | 3 | $files = Get-ChildItem "bld\TestResults" -Filter "*.coverage" -Recurse 4 | 5 | foreach ($file in $files) 6 | { 7 | $command = 'microsoft.codecoverage.16.10.0\build\netstandard1.0\CodeCoverage\CodeCoverage.exe analyze /output:' + $file.DirectoryName + '\' + $file.Name + '.xml '+ $file.FullName 8 | Write-Host $command 9 | Invoke-Expression $command 10 | } -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_009.LinkedInCredentials.ps1: -------------------------------------------------------------------------------- 1 | linkedin "0000000aaaaaaa" "00000000aaaaaaaa" 2 | 3 | # Xml style 4 | 5 | 1111111aaaaaaa 6 | 00000000aaaaaaaa 7 | 8 | 9 | # AppSettings style 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/RE2.Managed/Submatch.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Microsoft.RE2.Managed 7 | { 8 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 9 | public struct Submatch 10 | { 11 | public int Index; 12 | public int Length; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/RE2.Managed/GroupNameHeader.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Microsoft.RE2.Managed 7 | { 8 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 9 | public struct GroupNameHeader 10 | { 11 | public int Index; 12 | public int Length; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_002.GoogleOAuthCredentials.ps1: -------------------------------------------------------------------------------- 1 | 000000000000-orc0qcgp8ls5nkshbjs9p2erbkrffup8.apps.googleusercontent.com 2 | BsEiZJw3cl60wEToh-Fgctid 3 | 4 | var id = "111111111111-orc0qcgp8ls5nkshbjs9p2erbkrffup8.apps.googleusercontent.com"; 5 | var key = "BsEiZJw3cl60wEToh-Fgctid"; 6 | 7 | 222222222222-orc0qcgp8ls5nkshbjs9p2erbkrffup8.apps.googleusercontent.com 8 | BsEiZJw3cl60wEToh-Fgctid 9 | -------------------------------------------------------------------------------- /src/RE2.Native/Match2.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #pragma once 5 | #pragma pack(push, 1) 6 | 7 | // Represents the UTF8 position and length of a Regular Expression match within text. 8 | // Matches RE2.Managed\Match2.cs and must maintain identical layout. 9 | struct Match2 { 10 | __int32 Index; 11 | __int32 Length; 12 | }; 13 | #pragma pack(pop) -------------------------------------------------------------------------------- /src/RE2.Native/String8.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | #pragma once 5 | #pragma pack(push, 1) 6 | 7 | // Represents a block of UTF8 text in a slice of a byte array. 8 | // Matches RE2.Managed\String8.cs and must maintain identical layout. 9 | struct String8 { 10 | char* Array; 11 | __int32 Index; 12 | __int32 Length; 13 | }; 14 | 15 | #pragma pack(pop) -------------------------------------------------------------------------------- /targets/build.test.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | $(MsBuildThisFileDirectory)..\src\SarifPatternMatcher.runsettings 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_011.SquareCredentials.ps1: -------------------------------------------------------------------------------- 1 | # Code style 2 | var id = "sq0idp-5jnRMCM5UQ6GRrIi0HFeIA" 3 | var key = "sq0csp-1QurZKQX2KjDCVAHa-eSJL4Au1EmUpQj1hgn5xPH25A"; 4 | 5 | # Xml style 6 | sq0idp-5jnRMCM5UQ6GRrIi0HFeIA 7 | sq0csp-1QurZKQX2KjDCVAHa-eSJL4Au1EmUpQj1hgn5xPH25B 8 | 9 | # Json style 10 | { 11 | "id":"sq0idp-5jnRMCM5UQ6GRrIi0HFeIA", 12 | "secret":"sq0csp-1QurZKQX2KjDCVAHa-eSJL4Au1EmUpQj1hgn5xPH25C" 13 | } 14 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/UseSecureApi/Inputs/SEC104.Memory.Allocation_malloca.c: -------------------------------------------------------------------------------- 1 | #include // For _MAX_PATH definition 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | void* pData = NULL; 8 | 9 | // Allocate space for a path name 10 | pData = _malloca(_MAX_PATH); 11 | 12 | // In a C++ file, explicitly cast malloc's return. For example, 13 | // string = (char *)malloc( _MAX_PATH ); 14 | 15 | if (pData != NULL) 16 | { 17 | free(pData); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Function/FunctionConstants.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Function 5 | { 6 | public static class FunctionConstants 7 | { 8 | public static readonly string FileNamePropertyName = "filename"; 9 | public static readonly string FileContentPropertyName = "filecontent"; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Cli/DatabaseReaders/IDatabaseReader.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Cli.DatabaseReaders 5 | { 6 | internal interface IDatabaseReader 7 | { 8 | void Query(AnalyzeDatabaseOptions options); 9 | 10 | void ProcessBatch(string connection, string stepQuery, string identity); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher.Cli/SimplePatterns.json: -------------------------------------------------------------------------------- 1 | { 2 | "Definitions": [ 3 | { 4 | "Id": "SPM1000/COMPREHENSIVE_EXAMPLE", 5 | "Name": "Comprehensive Example Friendly Name", 6 | "FileNameAllowRegex": "(?i)\\.unlikelyfileextension$", 7 | "MatchExpressions": [ 8 | { 9 | "Notes": ["This is a simple comprehensive example of the JSON search patterns format."] 10 | "ContentsRegex": "Prefix(?MatchThis)Suffix" 11 | } 12 | ] 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_016.StripeApiKeyValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 7 | { 8 | [ValidatorDescriptor("SEC101/016")] 9 | public class StripeApiKeyValidator : StripeApiKeyValidatorBase 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/UseSecureApi/Inputs/SEC104.Memory.Allocation_alloca.c: -------------------------------------------------------------------------------- 1 | #include // For _MAX_PATH definition 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | void* pData = NULL; 8 | 9 | // Allocate space for a path name 10 | pData = _alloca(_MAX_PATH); 11 | 12 | // In a C++ file, explicitly cast malloc's return. For example, 13 | // string = (char *)malloc( _MAX_PATH ); 14 | 15 | if (pData != NULL) 16 | { 17 | free(pData); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_051.StripeTestApiKeyValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 7 | { 8 | [ValidatorDescriptor("SEC101/051")] 9 | public class StripeTestApiKeyValidator : StripeApiKeyValidatorBase 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/ReviewPotentiallySensitiveFiles/Inputs/SEC103_002.ASCIIArmoredFile_fake.asc: -------------------------------------------------------------------------------- 1 | Volume in drive E is DATADRIVE1 2 | Volume Serial Number is 1235-2302 3 | 4 | Directory of E:\src\spam\src\Plugins\Tests.Security\TestData\ReviewPotentiallySensitiveFiles\Inputs 5 | 6 | 12/17/2020 11:40 AM . 7 | 12/17/2020 11:40 AM .. 8 | 12/17/2020 11:40 AM 0 Fake.asc 9 | 1 File(s) 0 bytes 10 | 2 Dir(s) 11,484,848,128 bytes free 11 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_052.StripeLiveRestrictedKeyValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 7 | { 8 | [ValidatorDescriptor("SEC101/052")] 9 | public class StripeLiveRestrictedApiKeyValidator : StripeApiKeyValidatorBase 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Cli/Models/ContentSearchPatterns.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Xml.Serialization; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Cli.Models 7 | { 8 | [XmlRoot(ElementName = "ContentSearchPatterns")] 9 | public class ContentSearchPatterns 10 | { 11 | [XmlElement(ElementName = "string")] 12 | public string String { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_053.StripeTestRestrictedApiKeyValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 7 | { 8 | [ValidatorDescriptor("SEC101/053")] 9 | public class StripeTestRestrictedApiKeyValidator : StripeApiKeyValidatorBase 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Cli/Enums/ConnectionType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Cli.Enums 5 | { 6 | public enum ConnectionType 7 | { 8 | /// 9 | /// Kusto database. 10 | /// 11 | Kusto = 0, 12 | 13 | /// 14 | /// SqlLite database. 15 | /// 16 | SqlLite, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher/ValidationMethods.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Reflection; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 7 | { 8 | public class ValidationMethods 9 | { 10 | public MethodInfo IsValidStatic { get; set; } 11 | 12 | public MethodInfo IsValidDynamic { get; set; } 13 | 14 | public MethodInfo DisableDynamicValidationCaching { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Benchmark/Program.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using BenchmarkDotNet.Running; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Benchmark.Benchmarks; 7 | 8 | namespace Sarif.PatternMatcher.Benchmark 9 | { 10 | internal static class Program 11 | { 12 | private static void Main(string[] args) 13 | { 14 | BenchmarkRunner.Run(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_007.GitHubAppCredentials.ps1: -------------------------------------------------------------------------------- 1 | # Xml style 2 | 3 | 4 | deadbeef00deadbeef00deadbeef00testtest 5 | 6 | 7 | Iv1.01234567testtest 8 | 9 | 10 | # AppSettings style 11 | 12 | 13 | 14 | 15 | 16 | # Code style 17 | var myGitHubid = "Iv1.01234567deaddead"; 18 | var myGitHubAppSecret = "deadbeef00deaddead00deadbeef00deadbeef"; -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_026.MailgunApiCredentials.ps1: -------------------------------------------------------------------------------- 1 | # AppSettings style 2 | 3 | 4 | 5 | 6 | 7 | # JSON style 8 | { 9 | "MailgunDomain": "domain2.mailgun.org", 10 | "MailgunApiCredentials": "0deadbeef00deadbeef00deadbeef000" 11 | } 12 | 13 | # XML style 14 | domain3.mailgun.org 15 | 0deadbeef00deadbeef00deadbeef000 -------------------------------------------------------------------------------- /src/Plugins/Security/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Runtime.CompilerServices; 5 | 6 | [assembly: InternalsVisibleTo("Tests.Security, PublicKey=0024000004800000940000000602000000240000525341310004000001000100433fbf156abe9718142bdbd48a440e779a1b708fd21486ee0ae536f4c548edf8a7185c1e3ac89ceef76c15b8cc2497906798779a59402f9b9e27281fb15e7111566cdc9a9f8326301d45320623c5222089cf4d0013f365ae729fb0a9c9d15138042825cd511a0f3d4887a7b92f4c2749f81b410813d297b73244cf64995effb1")] 7 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Cli/Models/ArrayOfContentSearcher.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Xml.Serialization; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Cli.Models 8 | { 9 | [XmlRoot(ElementName = "ArrayOfContentSearcher")] 10 | public class ArrayOfContentSearcher 11 | { 12 | [XmlElement(ElementName = "ContentSearcher")] 13 | public List ContentSearcher { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Sdk/ValidatorDescriptorAttribute.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk 7 | { 8 | [AttributeUsage(AttributeTargets.Class, Inherited = false)] 9 | public class ValidatorDescriptorAttribute : Attribute 10 | { 11 | public ValidatorDescriptorAttribute(string id) 12 | { 13 | Id = id; 14 | } 15 | 16 | public string Id { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Plugins/Utilities.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 7 | { 8 | public static class Utilities 9 | { 10 | public static string CreateReturnValueForException(Exception e) 11 | { 12 | return nameof(ValidationState.Unknown) + 13 | "#An unexpected exception was caught during validation: " + 14 | e.ToString(); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_034.CredentialObject.ps1: -------------------------------------------------------------------------------- 1 | # Implemented in CredentialObjectConstructor 2 | $domainCredential = New-Object System.Management.Automation.PSCredential ("REDMOND\username1", "doodle_BLOB1"); 3 | 4 | PSCredential Credential = new PSCredential ( "username2" , "doodle_BLOB2"); 5 | 6 | new SqlCredential("username3", "doodle_BLOB3") 7 | 8 | # Implemented in CredentialObjectInitializer 9 | something = new PSCredential() 10 | { 11 | UserName = "username4", 12 | Password = "doodle_BLOB4", 13 | } 14 | 15 | new SqlCredential() 16 | { 17 | UserId = "username5", 18 | Password = "doodle_BLOB5", 19 | } -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher/Base64EncodingMatch.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 5 | { 6 | public class Base64EncodingMatch 7 | { 8 | public int MinMatchLength { get; set; } 9 | 10 | public int MaxMatchLength { get; set; } 11 | 12 | public bool IsValid() 13 | { 14 | return MinMatchLength > 0 && 15 | MaxMatchLength > 0 && 16 | MinMatchLength <= MaxMatchLength; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/RE2.Managed/RegexDefaults.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Text.RegularExpressions; 5 | 6 | namespace Microsoft.RE2.Managed 7 | { 8 | public static class RegexDefaults 9 | { 10 | public const RegexOptions DefaultOptionsCaseInsensitive = RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase; 11 | public const RegexOptions DefaultOptionsCaseSensitive = RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Sdk/FingerprintElements.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk 7 | { 8 | [Flags] 9 | internal enum FingerprintElements 10 | { 11 | None = 0, 12 | Id = 0x1, 13 | Host = 0x2, 14 | Part = 0x4, 15 | Path = 0x8, 16 | Port = 0x10, 17 | Scheme = 0x20, 18 | Secret = 0x40, 19 | Platform = 0x80, 20 | Resource = 0x100, 21 | Thumbprint = 0x200, 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_102.AdoPat.txt: -------------------------------------------------------------------------------- 1 | // This pattern matches the preliminary regex but 2 | // fails validation as 'NoMatch'. 3 | deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdead 4 | 5 | // This is a based64-encoded version of the pattern above. 6 | ZGVhZGJlZWZkZWFkYmVlZmRlYWRiZWVmZGVhZGJlZWZkZWFkYmVlZmRlYWRiZWVmZGVhZA== 7 | 8 | // This is a valid but expired AzureDevOps PAT 9 | h5lxeqkz4zujkyvzg5emkejgelxj4x64tvyzclprekuloawbbz5q 10 | 11 | // This is a based64-encoded version of the pattern above. 12 | aDVseGVxa3o0enVqa3l2emc1ZW1rZWpnZWx4ajR4NjR0dnl6Y2xwcmVrdWxvYXdiYno1cQ== 13 | 14 | /q6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urq6urA -------------------------------------------------------------------------------- /src/RE2.Managed/Match2.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Microsoft.RE2.Managed 7 | { 8 | /// 9 | /// Represents the UTF8 position and length of a Regular Expression match within text. 10 | /// 11 | /// 12 | /// Matches RE2.Native\Match2.h and must maintain identical layout. 13 | /// 14 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 15 | public struct Match2 16 | { 17 | public int Index; 18 | public int Length; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher/SearchDefinitions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 8 | { 9 | public class SearchDefinitions 10 | { 11 | public string SharedStringsFileName { get; set; } 12 | 13 | public string ValidatorsAssemblyName { get; set; } 14 | 15 | public string ExtensionName { get; set; } 16 | 17 | public Guid Guid { get; set; } 18 | 19 | public List Definitions { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Cli/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_035.CloudantCredentials.ps1: -------------------------------------------------------------------------------- 1 | # Taken from https://cloud.ibm.com/docs/Cloudant?topic=Cloudant-creating-and-populating-a-simple-ibm-cloudant-database-on-ibm-cloud 2 | client = Cloudant("apikey-v2-username1111165BB6673E1B79482A8C", 3 | "password1111123956157d94b25d574586f26d1211e8e589646b4713d5de4801", 4 | url="https://host1111-47eb-45ce-b125-4a4e1b5a4f7e-bluemix.cloudant.com") 5 | 6 | # 64 character alphanumeric password 7 | https://username2:password89012345678901234567890123456789012345678901234567890123@host22.cloudant.com 8 | 9 | # api keys are only 24 alphabetical characters 10 | https://username3:passwordijabcdefghijabcd@host33.cloudant.com -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher.Function/TestLogger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | using Microsoft.Extensions.Logging; 7 | 8 | namespace Test.UnitTest.Sarif.PatternMatcher.Function 9 | { 10 | public class TestLogger : ILogger 11 | { 12 | IDisposable ILogger.BeginScope(TState state) => null; 13 | 14 | bool ILogger.IsEnabled(LogLevel logLevel) => false; 15 | 16 | void ILogger.Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) 17 | { 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Plugins/Tests.SalModernization/TestData/UpdateSalToCurrentVersion/Inputs/SEC105_001.AnalysisAssume.cpp: -------------------------------------------------------------------------------- 1 | #define __allocator _SAL_L_Source_(__allocator, (), __inner_allocator) 2 | #define __deallocate(kind) _SAL_L_Source_(__deallocate, (kind), _Pre_ __notnull __post_invalid) 3 | #define __deallocate_opt(kind) _SAL_L_Source_(__deallocate_opt, (kind), _Pre_ __maybenull __post_invalid) 4 | 5 | 6 | 7 | __analysis_assume(IoControlCode == IOCTL_GPD_READ_PORT_UCHAR || \ 8 | IoControlCode == IOCTL_GPD_READ_PORT_USHORT || \ 9 | IoControlCode == IOCTL_GPD_READ_PORT_ULONG || \ 10 | IoControlCode == IOCTL_GPD_WRITE_PORT_UCHAR || \ 11 | IoControlCode == IOCTL_GPD_WRITE_PORT_USHORT || \ 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_032.GpgCredentials.ps1: -------------------------------------------------------------------------------- 1 | #Taken from https://www.saltycrane.com/blog/2011/10/python-gnupg-gpg-example/ 2 | 3 | # Implemented in GpgCredentialGenerateKey 4 | input_data = gpg.gen_key_input( 5 | name_email='username1@mydomain.com', 6 | passphrase='doodle_BLOB1') 7 | 8 | with open('my-encrypted.txt.gpg', 'rb') as f: 9 | status = gpg.decrypt_file(f, passphrase='doodle_BLOB2', output='my-decrypted.txt') 10 | 11 | # Taken from CodeAsData - Implemented in GpgCredentialGenerateKey 12 | gpg.gen_key_input(Passphrase='doodle_BLOB3') >>> key = gpg.gen_key(input) >>> assert key >>> sig = gpg.sign('hello',keyid=key.fingerprint,passphrase='doodle_BLOB4') >>> assert not sig >>> sig = g -------------------------------------------------------------------------------- /src/RE2.Managed/FlexMatch.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Strings.Interop; 5 | 6 | namespace Microsoft.RE2.Managed 7 | { 8 | /// 9 | /// FlexMatch is a generic subset of System.Text.RegularExpressions.Match. 10 | /// 11 | public class FlexMatch 12 | { 13 | public bool Success { get; set; } 14 | 15 | public int Index { get; set; } 16 | 17 | public int Length { get; set; } 18 | 19 | public FlexString Value { get; set; } 20 | 21 | public override string ToString() 22 | { 23 | return Value?.String ?? string.Empty; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_004.FacebookAppCredentials.ps1: -------------------------------------------------------------------------------- 1 | var facebookId = "111111111111111"; 2 | var facebookKey = "c9117d87046fc24205e4240e6bc9963a"; 3 | 4 | 222222222222222>/facebookId> 5 | c9117d87046fc24205e4240e6bc9963a 6 | 7 | FacebookTestAppKey=333333333333333 8 | FacebookTestAppSecret=c9117d87046fc24205e4240e6bc9963a 9 | 10 | { 11 | 'FacebookClientID' : '444444444444444', // your App ID 12 | 'FacebookClientSecret' : 'c9117d87046fc24205e4240e6bc9963a', // your App Secret 13 | } 14 | 15 | facebookId 555555555555555 16 | facebookSecret c9117d87046fc24205e4240e6bc9963a 17 | 18 | ## Invalid passowrd (does not have any digit) 19 | facebookId 555555555555555 20 | facebookSecret deaddeaddeaddeaddeaddeaddeaddead 21 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_033.MongoDbCredentials.ps1: -------------------------------------------------------------------------------- 1 | mongodb://dbuser1:@database.com:10250/database 2 | 3 | mongodb+srv://dbuser2:@database.com/ 4 | 5 | "mongodb": "mongodb+srv://dbuser3:@database.com" 6 | 7 | mongodb+srv://dbuser4:@database.com 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | mongodb://dbuser6:password@localhost:66666, 16 | mongodb://localhost:77777, -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher/TestAnalyzeCommand.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.CodeAnalysis.Sarif.Driver; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 7 | { 8 | public class TestAnalyzeCommand : AnalyzeCommand 9 | { 10 | protected override AnalyzeContext CreateScanTargetContext(AnalyzeContext globalContext) 11 | { 12 | globalContext = base.CreateScanTargetContext(globalContext); 13 | 14 | var aggregatingLogger = (AggregatingLogger)globalContext.Logger; 15 | aggregatingLogger.Loggers.Add(new TestLogger()); 16 | 17 | return globalContext; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/Plugins/Tests.SalModernization/EndToEndTestsSalModernization.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security; 5 | 6 | using Xunit.Abstractions; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.SalModernization 9 | { 10 | public abstract class EndToEndTestsSalModernization : EndToEndTests 11 | { 12 | public EndToEndTestsSalModernization(ITestOutputHelper outputHelper) : base(outputHelper) 13 | { 14 | } 15 | 16 | protected override string TestLogResourceNameRoot => $"Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.SalModernization.TestData.{TypeUnderTest}"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_029.AlibabaCloudCredentials.ps1: -------------------------------------------------------------------------------- 1 | nt from aliyunsdkcore.request import CommonRequest def getToken(): client = AcsClient( "LTAI01234567890123456789", "111111111101234567890123456789", "cn-shanghai" ); request = CommonRequest() ... 2 | nt from aliyunsdkcore.request import CommonRequest def getToken(): client = AcsClient( "LTAI012345A7890123456789", "111111111101234567890123456789", "cn-shanghai" ); request = CommonRequest() ... 3 | 4 | mNlsRequest.setApp_key("nls-service"); string id = "LTAI012345678901"; string scret = "222222222201234567890123456789"; mNlsRequest.authorize(id, scret); mNlsRequest.setTts_enable(true); //attention mNlsRequest.setTts_req(tts_text, "16000"); mNlsRequest.setTts... -------------------------------------------------------------------------------- /src/stylecop.json: -------------------------------------------------------------------------------- 1 | { 2 | // ACTION REQUIRED: This file was automatically added to your project, but it 3 | // will not take effect until additional steps are taken to enable it. See the 4 | // following page for additional information: 5 | // 6 | // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/EnableConfiguration.md 7 | 8 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", 9 | "settings": { 10 | "documentationRules": { 11 | "copyrightText": "Copyright (c) Microsoft. All rights reserved.\nLicensed under the MIT license. See LICENSE file in the project root for full license information.", 12 | "xmlHeader": false 13 | }, 14 | "readabilityRules": { 15 | 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/RE2.Managed/MatchesCaptureGroupsOutput.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Microsoft.RE2.Managed 7 | { 8 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 9 | public unsafe struct MatchesCaptureGroupsOutput 10 | { 11 | public GroupNameHeader* GroupNameHeaders; 12 | public byte* GroupNamesBuffer; 13 | public int NumGroupNames; 14 | public Submatch** Matches; 15 | public int NumMatches; 16 | public int NumSubmatches; 17 | 18 | private readonly void* groupNameHeadersCleanupPtr; 19 | private readonly void* groupNamesBufferCleanupPtr; 20 | private readonly void* matchesCleanupPtr; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Plugins/Tests.AzureDevOpsConfiguration/EndToEndTestsAzureDevOpsConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security; 5 | 6 | using Xunit.Abstractions; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.AzureDevOpsConfiguration 9 | { 10 | public abstract class EndToEndTestsAzureDevOpsConfiguration : EndToEndTests 11 | { 12 | public EndToEndTestsAzureDevOpsConfiguration(ITestOutputHelper outputHelper) : base(outputHelper) 13 | { 14 | } 15 | 16 | protected override string TestLogResourceNameRoot => $"Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.AzureDevOpsConfiguration.TestData.{TypeUnderTest}"; 17 | 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher/ValidateOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using CommandLine; 7 | 8 | using Microsoft.CodeAnalysis.Sarif.Driver; 9 | 10 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 11 | { 12 | [Verb("validate", HelpText = "Validate credentials persisted to SARIF log file.")] 13 | public class ValidateOptions : MultipleFilesOptionsBase 14 | { 15 | [Option( 16 | 'd', 17 | "search-definitions", 18 | Separator = ';', 19 | HelpText = "A path to a file containing one or more search definitions to drive analysis.")] 20 | public IEnumerable SearchDefinitionsPaths { get; internal set; } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Strings.Interop/Strings.Interop.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | String8 Library 7 | Specialized types for seamless handling of UTF8 and UTF16 strings. 8 | Microsoft.Strings.Interop 9 | Microsoft Strings Interop 10 | 11 | 12 | 13 | all 14 | runtime; build; native; contentfiles; analyzers 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Benchmark/Sarif.PatternMatcher.Benchmark.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(RootNamespaceBase).Sarif.PatternMatcher.Benchmark 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Cli/ExportConfigurationCommand.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Reflection; 6 | 7 | using Microsoft.CodeAnalysis.Sarif.Driver; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Cli 10 | { 11 | internal class ExportConfigurationCommand : ExportConfigurationCommandBase 12 | { 13 | public override IOptionsProvider AdditionalOptionsProvider => new AnalyzeContext(); 14 | 15 | public override IEnumerable DefaultPluginAssemblies { get => new List(); set => base.DefaultPluginAssemblies = value; } 16 | 17 | public override int Run(ExportConfigurationOptions exportOptions) 18 | { 19 | return base.Run(exportOptions); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/SEC104.UseSecureApiTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Xunit; 5 | using Xunit.Abstractions; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 8 | { 9 | public class UseSecureApiTests : EndToEndTests 10 | { 11 | public UseSecureApiTests(ITestOutputHelper outputHelper) : base(outputHelper) 12 | { 13 | } 14 | 15 | protected override string RuleId => "SEC104"; 16 | 17 | protected override string Framework => "netstandard2.1"; 18 | 19 | protected override string TypeUnderTest => "UseSecureApi"; 20 | 21 | [Fact] 22 | [Trait(TestTraits.WindowsOnly, "true")] 23 | public void UseSecureApi_EndToEndFunctionalTests() 24 | => RunAllTests(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/RE2.Managed/RE2.Managed.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | PreserveNewest 7 | 8 | 9 | PreserveNewest 10 | 11 | 12 | PreserveNewest 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/RE2.Managed/String8Interop.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Runtime.InteropServices; 5 | 6 | namespace Microsoft.RE2.Managed 7 | { 8 | /// 9 | /// Represents a block of UTF8 text in a slice of a byte array. 10 | /// 11 | /// 12 | /// Matches RE2.Native\String8.h and must maintain identical layout. 13 | /// 14 | [StructLayout(LayoutKind.Sequential, Pack = 1)] 15 | public unsafe struct String8Interop 16 | { 17 | public byte* Array; 18 | public int Index; 19 | public int Length; 20 | 21 | public String8Interop(byte* array, int index, int length) 22 | { 23 | this.Array = array; 24 | this.Index = index; 25 | this.Length = length; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Plugins/Security/Utilities/DictionaryExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.RE2.Managed; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 9 | { 10 | public static class DictionaryExtensions 11 | { 12 | public static bool TryGetNonEmptyValue(this IDictionary dictionary, TKey key, out FlexMatch value) 13 | { 14 | return dictionary.TryGetValue(key, out value) && !string.IsNullOrWhiteSpace(value.Value); 15 | } 16 | 17 | public static bool TryGetNonEmptyValue(this IDictionary dictionary, TKey key, out string value) 18 | { 19 | return dictionary.TryGetValue(key, out value) && !string.IsNullOrWhiteSpace(value); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Test.UnitTests.Strings.Interop/Test.UnitTests.Strings.Interop.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Microsoft.Strings.Interop 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | all 19 | runtime; build; native; contentfiles; analyzers; buildtransitive 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_041.RabbitMqCredentials.ps1: -------------------------------------------------------------------------------- 1 | # Simple string 2 | amqp://user:password@host/database1 3 | 4 | # Simple string as value 5 | "amqp://user:password@host/database2" 6 | 7 | # Simple string as XML 8 | amqps://user:password@host/database3 9 | 10 | # Simple string with port 11 | amqp://user:password@host:1234/database4 12 | 13 | # Simple string with default vhost 14 | "amqps://user:password@host:1234/" 15 | 16 | # Name/value pairs 17 | { "name": "RABBITMQ_HOST", "value": "12.23.45.78" }, { "name": "RABBITMQ_PASSWORD", "value": "pass@word" }, { "name": "RABBITMQ_PORT", "value": "5672" }, { "name": "RABBITMQ_USERNAME", "value": "guest" }, 18 | 19 | # This is invalid and should not be captured 20 | amqp://user:{{rabbitmq_password}}@host:1234/database4 21 | amqp://user:password@host:1234 /database5 22 | amqp://user:password@host:1234 23 | amqp://id:secret @host/resource 24 | amqp://id:secret 25 | @host/resource 26 | amqp://test":test@test/test -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/SEC102.ReviewPotentiallySensitiveDataTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Xunit; 5 | using Xunit.Abstractions; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 8 | { 9 | public class ReviewPotentiallySensitiveDataTests : EndToEndTests 10 | { 11 | public ReviewPotentiallySensitiveDataTests(ITestOutputHelper outputHelper) : base(outputHelper) 12 | { 13 | } 14 | 15 | protected override string RuleId => "SEC102"; 16 | 17 | protected override string Framework => "netstandard2.1"; 18 | 19 | protected override string TypeUnderTest => "ReviewPotentiallySensitiveData"; 20 | 21 | [Fact] 22 | [Trait(TestTraits.WindowsOnly, "true")] 23 | public void ReviewPotentiallySensitiveData_EndToEndFunctionalTests() 24 | => RunAllTests(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Plugins/Tests.SalModernization/SEC105.UpdateSalToCurrentVersion.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Xunit; 5 | using Xunit.Abstractions; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.SalModernization 8 | { 9 | public class UpdateSalToCurrentVersionTests : EndToEndTestsSalModernization 10 | { 11 | public UpdateSalToCurrentVersionTests(ITestOutputHelper outputHelper) : base(outputHelper) 12 | { 13 | } 14 | 15 | protected override string RuleId => "SEC105"; 16 | 17 | protected override string Framework => "netstandard2.0"; 18 | 19 | protected override string TypeUnderTest => "UpdateSalToCurrentVersion"; 20 | 21 | [Fact] 22 | [Trait(TestTraits.WindowsOnly, "true")] 23 | public void UpdateSalToCurrentVersion_EndToEndFunctionalTests() 24 | => RunAllTests(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/SEC103.ReviewPotentiallySensitiveFilesTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Xunit; 5 | using Xunit.Abstractions; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 8 | { 9 | public class ReviewPotentiallySensitiveFilesTests : EndToEndTests 10 | { 11 | public ReviewPotentiallySensitiveFilesTests(ITestOutputHelper outputHelper) : base(outputHelper) 12 | { 13 | } 14 | 15 | protected override string RuleId => "SEC103"; 16 | 17 | protected override string Framework => "netstandard2.1"; 18 | 19 | protected override string TypeUnderTest => "ReviewPotentiallySensitiveFiles"; 20 | 21 | [Fact] 22 | [Trait(TestTraits.WindowsOnly, "true")] 23 | public void ReviewPotentiallySensitiveFiles_EndToEndFunctionalTests() 24 | => RunAllTests(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Plugins/Tests.AzureDevOpsConfiguration/AZC101.BuildDefinitionSecurityTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Xunit; 5 | using Xunit.Abstractions; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.AzureDevOpsConfiguration 8 | { 9 | public class BuildDefinitionSecurityTests : EndToEndTestsAzureDevOpsConfiguration 10 | { 11 | public BuildDefinitionSecurityTests(ITestOutputHelper outputHelper) : base(outputHelper) 12 | { 13 | } 14 | 15 | protected override string RuleId => "AZC101"; 16 | 17 | protected override string Framework => "netstandard2.1"; 18 | 19 | protected override string TypeUnderTest => "BuildDefinitionSecurity"; 20 | 21 | [Fact] 22 | [Trait(TestTraits.WindowsOnly, "true")] 23 | public void AzureDevOpsConfiguration_EndToEndFunctionalTests() 24 | => RunAllTests(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Cli/ExportRulesMetatadaOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using CommandLine; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Cli 9 | { 10 | [Verb("export-rules", HelpText = "Export rules metadata to a markdown (*.md) file.")] 11 | internal class ExportRulesMetatadaOptions 12 | { 13 | [Value( 14 | 0, 15 | HelpText = "Output path for exported rules data as markdown (*.md).", 16 | Required = true)] 17 | public string OutputFilePath { get; set; } 18 | 19 | [Option( 20 | 'd', 21 | "search-definitions", 22 | Separator = ';', 23 | HelpText = "A path to a file containing one or more search definitions to drive analysis.")] 24 | public IEnumerable SearchDefinitionsPaths { get; set; } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /scripts/BuildPackages.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Build packages from compiled dlls. 4 | .PARAMETER Configuration 5 | The build configuration: Release or Debug. Default=Release 6 | #> 7 | 8 | [CmdletBinding()] 9 | param( 10 | [string] 11 | [ValidateSet("Debug", "Release")] 12 | $Configuration="Release" 13 | ) 14 | 15 | Set-StrictMode -Version Latest 16 | $ErrorActionPreference = "Stop" 17 | $InformationPreference = "Continue" 18 | 19 | $ScriptName = $([io.Path]::GetFileNameWithoutExtension($PSCommandPath)) 20 | $RepoRoot = $(Resolve-Path $PSScriptRoot\..).Path 21 | 22 | function Exit-WithFailureMessage($scriptName, $message) { 23 | Write-Information "${scriptName}: $message" 24 | Write-Information "$scriptName FAILED." 25 | exit 1 26 | } 27 | 28 | dotnet pack "$RepoRoot\src\SarifPatternMatcher.sln" --no-build --configuration $Configuration --force 29 | if ($LASTEXITCODE -ne 0) { 30 | Exit-WithFailureMessage $ScriptName "Pack of SarifPatternMatcher.sln failed." 31 | } 32 | 33 | Write-Information "$ScriptName SUCCEEDED." -------------------------------------------------------------------------------- /src/Plugins/Tests.AzureDevOpsConfiguration/AZC102.ServiceConnectionSecurityTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Xunit; 5 | using Xunit.Abstractions; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.AzureDevOpsConfiguration 8 | { 9 | public class ServiceConnectionSecurityTests : EndToEndTestsAzureDevOpsConfiguration 10 | { 11 | public ServiceConnectionSecurityTests(ITestOutputHelper outputHelper) : base(outputHelper) 12 | { 13 | } 14 | 15 | protected override string RuleId => "AZC102"; 16 | 17 | protected override string Framework => "netstandard2.1"; 18 | 19 | protected override string TypeUnderTest => "ServiceConnectionSecurity"; 20 | 21 | [Fact] 22 | [Trait(TestTraits.WindowsOnly, "true")] 23 | public void AzureDevOpsConfiguration_EndToEndFunctionalTests() 24 | => RunAllTests(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher/RegexMetadata.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 7 | { 8 | [Flags] 9 | public enum RegexMetadata 10 | { 11 | /// 12 | /// Implicitly, the absence of any regex metadata means 13 | /// that it is a required match. That is, if the regex 14 | /// does not exist, the analysis rules halts immediately. 15 | /// 16 | None = 0, 17 | 18 | /// 19 | /// Indicates that the regex retrieves an optionally 20 | /// available value. 21 | /// 22 | Optional = 0x1, 23 | 24 | /// 25 | /// Indicates that the regex is potentially shared across 26 | /// multiple rules (and therefore can be cached). 27 | /// 28 | Shared = 0x2, 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/.ruleset: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_015.AkamaiCredentials.ps1: -------------------------------------------------------------------------------- 1 | https://akab-xxxxx-yyyyy.purge.akamaiapis.net/ccu/v2/queues/default 2 | EG1-HMAC-SHA256 client_token=akab-client-token-xxx-xxxxxxxxxxxxxxxx;access_token=akab-access-token-xxx-xxxxxxxxxxxxxxxx;timestamp=2021-03-25T19:18:12+0000;nonce=5c43bd4d-4dcd-4e22-b64b-efaa1a20047d;client_secret=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= 3 | 4 | "base_url": "https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/", 5 | "client_token": "akab-client-token-xxx-xxxxxxxxxxxxxxxx", 6 | "access_token": "akab-access-token-xxx-xxxxxxxxxxxxxxxx", 7 | "client_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=", 8 | 9 | ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss 10 | 11 | "base_url": "https://akaa-baseurl-xxxxxxxxxxx-xxxxxxxxxxxxx.luna.akamaiapis.net/", 12 | "access_token": "akab-access-token-xxx-xxxxxxxxxxxyyyyy", 13 | "client_token": "akab-client-token-xxx-xxxxxxxxxxxxxxxx", 14 | "client_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx=", 15 | -------------------------------------------------------------------------------- /src/Test.UnitTests.RE2.Managed/FlexMatchTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using FluentAssertions; 5 | 6 | using Microsoft.Strings.Interop; 7 | 8 | using Xunit; 9 | 10 | namespace Microsoft.RE2.Managed 11 | { 12 | public class FlexMatchTests 13 | { 14 | [Fact] 15 | public void FlexMatch_ShouldNotThrow() 16 | { 17 | var flexMatch = new FlexMatch(); 18 | flexMatch.ToString().Should().Be(string.Empty); 19 | 20 | flexMatch.Value = new FlexString(null); 21 | flexMatch.ToString().Should().Be(string.Empty); 22 | 23 | flexMatch.Value = new FlexString("flexMatch"); 24 | flexMatch.ToString().Should().Be("flexMatch"); 25 | 26 | byte[] buffer = null; 27 | var value = String8.Convert("flexMatch", ref buffer); 28 | flexMatch.Value = new FlexString(value); 29 | flexMatch.ToString().Should().Be("flexMatch"); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Microsoft Corporation 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Cli/Models/ContentSearcher.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Xml.Serialization; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Cli.Models 7 | { 8 | [XmlRoot(ElementName = "ContentSearcher")] 9 | public class ContentSearcher 10 | { 11 | [XmlElement(ElementName = "Name")] 12 | public string Name { get; set; } 13 | 14 | [XmlElement(ElementName = "RuleId")] 15 | public string RuleId { get; set; } 16 | 17 | [XmlElement(ElementName = "ResourceMatchPattern")] 18 | public string ResourceMatchPattern { get; set; } 19 | 20 | [XmlElement(ElementName = "ContentSearchPatterns")] 21 | public ContentSearchPatterns ContentSearchPatterns { get; set; } 22 | 23 | [XmlElement(ElementName = "FullMatchDetails")] 24 | public string FullMatchDetails { get; set; } 25 | 26 | [XmlElement(ElementName = "Severity")] 27 | public int Severity { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/RE2.Native/MatchesCaptureGroupsOutput.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | /* 5 | The `#pragma pack(push, 1)` directive ensures there is no padding between members of the struct. 6 | 7 | I am not sure if the `alignas(1)` attribute is necessary. I want to ensure that no padding is 8 | added to the beginning or end of the struct in any context. 9 | */ 10 | 11 | #pragma once 12 | #pragma pack(push, 1) 13 | 14 | #include 15 | 16 | #include 17 | 18 | #include "GroupNameHeader.h" 19 | #include "Submatch.h" 20 | 21 | struct MatchesCaptureGroupsOutput { 22 | GroupNameHeader* groupNameHeaders; 23 | uint8_t* groupNamesBuffer; 24 | int numGroupNames; 25 | Submatch** matches; 26 | int numMatches; 27 | int numSubmatches; 28 | 29 | std::vector* groupNameHeadersCleanupPtr; 30 | std::vector* groupNamesBufferCleanupPtr; 31 | std::vector* matchesCleanupPtr; 32 | }; 33 | 34 | #pragma pack(pop) 35 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_031.NuGetApiKeyValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/031")] 12 | public class NuGetApiKeyValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | FlexMatch secret = groups["secret"]; 17 | 18 | var validationResult = new ValidationResult 19 | { 20 | Fingerprint = new Fingerprint 21 | { 22 | Secret = secret.Value, 23 | Platform = nameof(AssetPlatform.NuGet), 24 | }, 25 | }; 26 | 27 | return new[] { validationResult }; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | pr: 2 | - "main" 3 | 4 | jobs: 5 | - job: NET_pipeline 6 | strategy: 7 | matrix: 8 | linux: 9 | imageName: "ubuntu-20.04" 10 | mac: 11 | imageName: "macOS-latest" 12 | windows: 13 | imageName: "windows-latest" 14 | maxParallel: 4 15 | 16 | pool: 17 | vmImage: $(imageName) 18 | 19 | steps: 20 | - task: UseDotNet@2 21 | displayName: .NET Core 3.1 sdk 22 | inputs: 23 | version: "3.1.x" 24 | packageType: sdk 25 | 26 | - task: UseDotNet@2 27 | displayName: .NET Core 6.0 sdk 28 | inputs: 29 | version: "6.0.x" 30 | packageType: sdk 31 | 32 | - task: PowerShell@2 33 | displayName: Build and Test 34 | inputs: 35 | targetType: filePath 36 | filePath: ./scripts/BuildAndTest.ps1 37 | arguments: "-Configuration Release -EnableCoverage" 38 | 39 | - task: PublishTestResults@2 40 | inputs: 41 | testRunner: VSTest 42 | testResultsFiles: "**/*.trx" 43 | 44 | - task: ComponentGovernanceComponentDetection@0 45 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_024.TwilioApiKeyValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/024")] 12 | public class TwilioApiKeyValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | FlexMatch secret = groups["secret"]; 17 | 18 | var validationResult = new ValidationResult 19 | { 20 | Fingerprint = new Fingerprint() 21 | { 22 | Secret = secret.Value, 23 | Platform = nameof(AssetPlatform.Twilio), 24 | }, 25 | }; 26 | 27 | return new[] { validationResult }; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_019.PicaticApiKeyValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/019")] 12 | public class PicaticApiKeyValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | FlexMatch secret = groups["secret"]; 17 | 18 | var validationResult = new ValidationResult 19 | { 20 | Fingerprint = new Fingerprint() 21 | { 22 | Secret = secret.Value, 23 | Platform = nameof(AssetPlatform.Picatic), 24 | }, 25 | }; 26 | 27 | return new[] { validationResult }; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_023.AmazonMwsAuthTokenValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/023")] 12 | public class AmazonMwsAuthTokenValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | FlexMatch secret = groups["secret"]; 17 | 18 | var validationResult = new ValidationResult 19 | { 20 | Fingerprint = new Fingerprint 21 | { 22 | Secret = secret.Value, 23 | Platform = nameof(AssetPlatform.Aws), 24 | }, 25 | }; 26 | 27 | return new[] { validationResult }; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_042.DynatraceTokenValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/042")] 12 | public class DynatraceTokenValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | FlexMatch secret = groups["secret"]; 17 | 18 | var validationResult = new ValidationResult 19 | { 20 | Fingerprint = new Fingerprint() 21 | { 22 | Secret = secret.Value, 23 | Platform = nameof(AssetPlatform.Dynatrace), 24 | }, 25 | }; 26 | 27 | return new[] { validationResult }; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_039.ShopifyAccessTokenValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/039")] 12 | public class ShopifyAccessTokenValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | FlexMatch secret = groups["secret"]; 17 | 18 | var validationResult = new ValidationResult 19 | { 20 | Fingerprint = new Fingerprint() 21 | { 22 | Secret = secret.Value, 23 | Platform = nameof(AssetPlatform.Shopify), 24 | }, 25 | }; 26 | 27 | return new[] { validationResult }; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_040.ShopifySharedSecretValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/040")] 12 | public class ShopifySharedSecretValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | FlexMatch secret = groups["secret"]; 17 | 18 | var validationResult = new ValidationResult 19 | { 20 | Fingerprint = new Fingerprint() 21 | { 22 | Secret = secret.Value, 23 | Platform = nameof(AssetPlatform.Shopify), 24 | }, 25 | }; 26 | 27 | return new[] { validationResult }; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_014.FacebookAccessTokenValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/014")] 12 | public class FacebookAccessTokenValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | FlexMatch secret = groups["secret"]; 17 | 18 | var validationResult = new ValidationResult 19 | { 20 | Fingerprint = new Fingerprint() 21 | { 22 | Secret = secret.Value, 23 | Platform = nameof(AssetPlatform.Facebook), 24 | }, 25 | }; 26 | 27 | return new[] { validationResult }; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/SEC101.SecurePlaintextSecretsTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Xunit; 5 | using Xunit.Abstractions; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 8 | { 9 | public class SecurePlaintextSecretsTests : EndToEndTests 10 | { 11 | public SecurePlaintextSecretsTests(ITestOutputHelper outputHelper) : base(outputHelper) 12 | { 13 | } 14 | 15 | protected override string RuleId => "SEC101"; 16 | 17 | protected override string Framework => "netstandard2.1"; 18 | 19 | protected override string TypeUnderTest => "SecurePlaintextSecrets"; 20 | 21 | [Fact] 22 | [Trait(TestTraits.WindowsOnly, "true")] 23 | public void SecurePlaintextSecrets_EndToEndFunctionalTests() 24 | => RunAllTests(); 25 | 26 | [Fact] 27 | public void SecurePlaintextSecrets_VerifyAllValidatorsExist() 28 | { 29 | PatternInvariantTests.VerifyAllValidatorsExist(DefinitionsPath); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Test.UnitTests.RE2.Managed/Test.UnitTests.RE2.Managed.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Microsoft.RE2.Managed 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | all 24 | runtime; build; native; contentfiles; analyzers; buildtransitive 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_022.PayPalBraintreeAccessTokenValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/022")] 12 | public class PayPalBraintreeAccessTokenValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | FlexMatch secret = groups["secret"]; 17 | 18 | var validationResult = new ValidationResult 19 | { 20 | Fingerprint = new Fingerprint() 21 | { 22 | Secret = secret.Value, 23 | Platform = nameof(AssetPlatform.PayPal), 24 | }, 25 | }; 26 | 27 | return new[] { validationResult }; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Plugins/SalModernization/build/Sarif.PatternMatcher.SalModernization.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 16 | 17 | 20 | 23 | 24 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_032.GpgCredentialsValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/032")] 12 | public class GpgCredentialsValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | FlexMatch secret = groups["secret"]; 17 | 18 | groups.TryGetNonEmptyValue("id", out FlexMatch id); 19 | 20 | var validationResult = new ValidationResult 21 | { 22 | Fingerprint = new Fingerprint() 23 | { 24 | Id = id?.Value, 25 | Secret = secret.Value, 26 | }, 27 | }; 28 | 29 | return new[] { validationResult }; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher.Sdk/Test.UnitTests.Sarif.PatternMatcher.Sdk.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $(RootNamespaceBase).Sarif.PatternMatcher.Sdk 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | all 24 | runtime; build; native; contentfiles; analyzers; buildtransitive 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/ExpectedOutputs/SEC101_047.CratesApiKey.sarif: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.6.json", 3 | "version": "2.1.0", 4 | "runs": [ 5 | { 6 | "tool": { 7 | "driver": { 8 | "name": "Spmi", 9 | "organization": "Microsoft", 10 | "product": "Microsoft SARIF Pattern Matcher", 11 | "fullName": "Sarif.PatternMatcher ", 12 | "properties": { 13 | "comments": "A general pattern matching engine that persist results to SARIF." 14 | } 15 | }, 16 | "extensions": [ 17 | { 18 | "guid": "6e04e237-f14b-4ff9-9cd8-e037a10cb510", 19 | "name": "Microsoft/Security/DoNotExposePlaintextSecrets", 20 | "locations": [ 21 | { 22 | "uri": "SEC101.SecurePlaintextSecrets.json", 23 | "uriBaseId": "EXTENSION_ROOT" 24 | } 25 | ] 26 | } 27 | ] 28 | }, 29 | "invocations": [ 30 | { 31 | "executionSuccessful": true 32 | } 33 | ], 34 | "columnKind": "utf16CodeUnits" 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_008.AwsCredentials.ps1: -------------------------------------------------------------------------------- 1 | # Xml style 2 | 3 | AKIAIOSFODNN7EXAMPLE 4 | 5 | test1test2test3test4test5test6test7 6 | test1test2test3test4test5test6test7 7 | test1test2test3test4test5test6test7 8 | test1test2test3test4test5test6test7 9 | test1test2test3test4test5test6test7 10 | test1test2test3test4test5test6test7 11 | test1test2test3test4test5test6test7 12 | One more line and the regex fails to match 13 | 14 | wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY 15 | 16 | 17 | AKIAIOSFODNN7EXAMPLE 18 | xJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY 19 | 20 | # AppSettings style 21 | 22 | 23 | 24 | 25 | 26 | # Code style 27 | var myAWSAccessKeyId = "AKIAIOSFODNN7EXAMPLE"; 28 | var myAWSSecretAccessKey = "zJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"; -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Sdk/Sarif.PatternMatcher.Sdk.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Sarif Pattern Matcher Sdk 8 | A general pattern matching Sdk that persist results to SARIF. 9 | $(RootNamespaceBase).Sarif.PatternMatcher.Sdk 10 | 11 | 12 | 13 | true 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | all 24 | runtime; build; native; contentfiles; analyzers 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_006.GitHubLegacyPat.ps1: -------------------------------------------------------------------------------- 1 | # ************ Below caught in $SEC101/006.GitHubLegacyPat 2 | 3 | # Xml style 4 | 5 | ff34885a8624460a855540c6592698d2f1812843 6 | 7 | 8 | # AppSettings style 9 | 10 | 11 | 12 | 13 | # Code style 14 | var myGitHubPersonalAccessToken = "ff34885a8624460a855540c6592698d2f181dead"; 15 | 16 | # Link style 17 | # This should trigger, but it should report as NoMatch 18 | https://github.com/microsoft/sarif-pattern-matcher/commit/4196919fb12cc4aa8ec0159a746c1e03b4ffa89c 19 | https://avatars0.githubusercontent.com/u/16199012?u=4196919fb12cc4aa8ec0159a746c1e03b4ffa89c&v=4 20 | https://github.com/microsoft/sarif-pattern-matcher/tree/7af498925c89a9e8c07fb8a65223e89d513d4eea 21 | 22 | # This should trigger, but it should report as NoMatch 23 | GitHubTriggersShouldReturnBothSourceRepoAndPullRequestTriggers 24 | 25 | # ************ Below caught in $SEC101/006.GitHubPat_2021_04_05 26 | 27 | # Personal access token 28 | ghp_000000000001234567890123456789012345 29 | 30 | # Refresh token 31 | ghr_111111111101234567890123456789012345 -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/ExpectedOutputs/SEC101_001.HttpAuthorizationRequestHeader.sarif: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.6.json", 3 | "version": "2.1.0", 4 | "runs": [ 5 | { 6 | "tool": { 7 | "driver": { 8 | "name": "Spmi", 9 | "organization": "Microsoft", 10 | "product": "Microsoft SARIF Pattern Matcher", 11 | "fullName": "Sarif.PatternMatcher ", 12 | "properties": { 13 | "comments": "A general pattern matching engine that persist results to SARIF." 14 | } 15 | }, 16 | "extensions": [ 17 | { 18 | "guid": "6e04e237-f14b-4ff9-9cd8-e037a10cb510", 19 | "name": "Microsoft/Security/DoNotExposePlaintextSecrets", 20 | "locations": [ 21 | { 22 | "uri": "SEC101.SecurePlaintextSecrets.json", 23 | "uriBaseId": "EXTENSION_ROOT" 24 | } 25 | ] 26 | } 27 | ] 28 | }, 29 | "invocations": [ 30 | { 31 | "executionSuccessful": true 32 | } 33 | ], 34 | "columnKind": "utf16CodeUnits" 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /src/Plugins/Tests.AzureDevOpsConfiguration/TestData/BuildDefinitionSecurity/ExpectedOutputs/AZC101.builddefinition.NoIssue.sarif: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.6.json", 3 | "version": "2.1.0", 4 | "runs": [ 5 | { 6 | "tool": { 7 | "driver": { 8 | "name": "Spmi", 9 | "organization": "Microsoft", 10 | "product": "Microsoft SARIF Pattern Matcher", 11 | "fullName": "Sarif.PatternMatcher ", 12 | "properties": { 13 | "comments": "A general pattern matching engine that persist results to SARIF." 14 | } 15 | }, 16 | "extensions": [ 17 | { 18 | "guid": "183f9c88-1424-4f6c-a8a5-cd59c0bdc312", 19 | "name": "Microsoft/AzureDevOpsConfiguration/SecureAzureDevOps", 20 | "locations": [ 21 | { 22 | "uri": "AZC101.BuildDefinitionSecurity.json", 23 | "uriBaseId": "EXTENSION_ROOT" 24 | } 25 | ] 26 | } 27 | ] 28 | }, 29 | "invocations": [ 30 | { 31 | "executionSuccessful": true 32 | } 33 | ], 34 | "columnKind": "utf16CodeUnits" 35 | } 36 | ] 37 | } -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_030.GoogleServiceAccountKeyValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/030")] 12 | public class GoogleServiceAccountKeyValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | FlexMatch secret = groups["secret"]; 17 | 18 | // We might not successfully retrieve the account id. 19 | groups.TryGetNonEmptyValue("id", out FlexMatch id); 20 | 21 | var validationResult = new ValidationResult 22 | { 23 | Fingerprint = new Fingerprint() 24 | { 25 | Id = id?.Value, 26 | Secret = secret.Value, 27 | }, 28 | }; 29 | 30 | return new[] { validationResult }; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Plugins/Security/build/Sarif.PatternMatcher.Security.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | 16 | 17 | 20 | 23 | 24 | 27 | 28 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher.Cli/TestValidators/StaticValidatorExistsForMatchExpressionValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Cli.TestValidators 10 | { 11 | [ValidatorDescriptor(Id)] 12 | internal class StaticValidatorExistsForMatchExpressionValidator : StaticValidatorBase 13 | { 14 | internal const string Id = "TEST001/002"; 15 | 16 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 17 | { 18 | string secret = groups["0"].Value; 19 | 20 | var validationResult = new ValidationResult 21 | { 22 | Fingerprint = new Fingerprint 23 | { 24 | Platform = nameof(AssetPlatform.Unknown), 25 | Secret = secret, 26 | }, 27 | ValidationState = ValidationState.Unknown, 28 | }; 29 | 30 | return new[] { validationResult }; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher/BadlyBehavedRule.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Composition; 7 | 8 | using Microsoft.CodeAnalysis.Sarif.Driver; 9 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher; 10 | 11 | namespace Microsoft.CodeAnalysis.Sarif 12 | { 13 | // Test rule for provoking various behaviors designed to increase code coverage. This rule can be configured 14 | // via explicitly passed configuration, by injecting test behaviors into a thread static variable, or 15 | // implicitly via the name of the scan targets. 16 | [Export(typeof(ReportingDescriptor)), Export(typeof(IOptionsProvider)), Export(typeof(Skimmer))] 17 | internal class BadlyBehavedRule : SpamTestRule 18 | { 19 | public override string Id => "5665000b-b7ad-48fb-8a70-47468d8d8338"; 20 | 21 | public override void Analyze(AnalyzeContext context) 22 | { 23 | throw new NotImplementedException(); 24 | } 25 | 26 | public new IEnumerable GetOptions() 27 | { 28 | throw new NotImplementedException(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher/SimpleFix.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 5 | { 6 | public class SimpleFix 7 | { 8 | /// 9 | /// Gets or sets a string value that describes this fix. This property 10 | /// will be used to label the fix in the IDE UX for invoking replacement 11 | /// operations. 12 | /// 13 | public string Description { get; set; } 14 | 15 | /// 16 | /// Gets or sets a string value representing text that should be replaced 17 | /// in the match. This string can contain named arguments, e.g., 18 | /// '{scanTarget}'. These arguments will be expanded before the replacement. 19 | /// 20 | public string Find { get; set; } 21 | 22 | /// 23 | /// Gets or sets a string value representing text that should injected into the match. 24 | /// This string can contain named arguments, e.g., '{scanTarget}'. These 25 | /// arguments will be expanded before the replacement. 26 | /// 27 | public string ReplaceWith { get; set; } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_028.PlaintextPasswordValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/028")] 12 | public class PlaintextPasswordValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | FlexMatch secret = groups["secret"]; 17 | 18 | var validationResult = new ValidationResult 19 | { 20 | Fingerprint = new Fingerprint() 21 | { 22 | Secret = secret.Value, 23 | }, 24 | ResultLevelKind = new ResultLevelKind 25 | { 26 | Level = FailureLevel.Warning, 27 | }, 28 | ValidationState = ValidationState.Authorized, 29 | }; 30 | 31 | return new[] { validationResult }; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_047.CratesApiKeyValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/047")] 12 | public class CratesApiKeyValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | FlexMatch secret = groups["secret"]; 17 | 18 | if (!secret.Value.ToString().ContainsDigitAndLetter()) 19 | { 20 | return ValidationResult.CreateNoMatch(); 21 | } 22 | 23 | var validationResult = new ValidationResult 24 | { 25 | Fingerprint = new Fingerprint 26 | { 27 | Secret = secret.Value, 28 | Platform = nameof(AssetPlatform.Crates), 29 | }, 30 | }; 31 | 32 | return new[] { validationResult }; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_034.CredentialObjectValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/034")] 12 | public class CredentialObjectValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | if (!groups.TryGetNonEmptyValue("id", out FlexMatch id) || 17 | !groups.TryGetNonEmptyValue("secret", out FlexMatch secret)) 18 | { 19 | return ValidationResult.CreateNoMatch(); 20 | } 21 | 22 | var validationResult = new ValidationResult 23 | { 24 | Fingerprint = new Fingerprint() 25 | { 26 | Id = id.Value, 27 | Secret = secret.Value, 28 | }, 29 | }; 30 | 31 | return new[] { validationResult }; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Plugins/AzureDevOpsConfiguration/build/Sarif.PatternMatcher.AzureDevOpsConfiguration.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | $(MSBuildThisFileDirectory)..\lib\netstandard2.1 9 | 10 | 11 | 12 | 13 | 16 | 19 | 20 | 23 | 26 | 27 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher/SearchDefinition.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.Driver; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 9 | { 10 | public class SearchDefinition 11 | { 12 | public string ExtensionName { get; set; } 13 | 14 | public Dictionary SharedStrings { get; set; } 15 | 16 | public string Id { get; set; } 17 | 18 | public string Name { get; set; } 19 | 20 | public string HelpUri { get; set; } 21 | 22 | public string Message { get; set; } 23 | 24 | public ResultKind Kind { get; set; } 25 | 26 | public RuleEnabledState RuleEnabledState { get; set; } 27 | 28 | public FailureLevel Level { get; set; } 29 | 30 | public string Description { get; set; } 31 | 32 | public string FileNameDenyRegex { get; set; } 33 | 34 | public string FileNameAllowRegex { get; set; } 35 | 36 | public List MatchExpressions { get; set; } 37 | 38 | #if DEBUG 39 | 40 | public override string ToString() 41 | { 42 | return $"{Id}.{Name}:{Level}"; 43 | } 44 | 45 | #endif 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher/SpamEventNames.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 5 | { 6 | public sealed class SpamEventNames 7 | { 8 | public const string ScanArtifact = nameof(RunRule); 9 | 10 | public const string Sniffing = nameof(Sniffing); 11 | public const string PostSniff = nameof(PostSniff); 12 | 13 | public const string RunRule = nameof(RunRule); 14 | 15 | public const string Phase0Sniff = "Phase0-Sniff"; 16 | public const string Phase1Regex = "Phase1-Regex"; 17 | public const string Phase2StaticValidation = "Phase2-StaticValidation"; 18 | public const string Phase3DynamicValidation = "Phase3-DynamicValidation"; 19 | 20 | public const string RunRulePhase0Sniff = $"{RunRule}/{Phase0Sniff}"; 21 | public const string RunRulePhase1Regex = $"{RunRule}/{Phase1Regex}"; 22 | public const string RunRulePhase2StaticValidation = $"{RunRule}/{Phase2StaticValidation}"; 23 | public const string RunRulePhase3DynamicValidation = $"{RunRule}/{Phase3DynamicValidation}"; 24 | 25 | // Reasons for various filtering conditions. 26 | public const string ContentsSniffNoMatch = nameof(ContentsSniffNoMatch); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher/Test.UnitTests.Sarif.PatternMatcher.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $(RootNamespaceBase).Sarif.PatternMatcher 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | all 26 | runtime; build; native; contentfiles; analyzers; buildtransitive 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_002.GoogleOAuthCredentialsValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/002")] 12 | public class GoogleOAuthCredentialsValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | if (!groups.TryGetValue("id", out FlexMatch id) || 17 | !groups.TryGetValue("secret", out FlexMatch secret)) 18 | { 19 | return ValidationResult.CreateNoMatch(); 20 | } 21 | 22 | var validationResult = new ValidationResult 23 | { 24 | Fingerprint = new Fingerprint 25 | { 26 | Id = id.Value, 27 | Secret = secret.Value, 28 | Platform = nameof(AssetPlatform.Google), 29 | }, 30 | }; 31 | 32 | return new[] { validationResult }; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/RE2.Managed/FlexMatchValueComparer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.RE2.Managed 7 | { 8 | public class FlexMatchValueComparer : IEqualityComparer 9 | { 10 | private static FlexMatchValueComparer _instance; 11 | 12 | public static FlexMatchValueComparer Instance 13 | { 14 | get 15 | { 16 | _instance ??= new FlexMatchValueComparer(); 17 | return _instance; 18 | } 19 | } 20 | 21 | public bool Equals(FlexMatch left, FlexMatch right) 22 | { 23 | if (ReferenceEquals(left, right)) 24 | { 25 | return true; 26 | } 27 | 28 | if (ReferenceEquals(left, null) || ReferenceEquals(right, null)) 29 | { 30 | return false; 31 | } 32 | 33 | return left.Value?.String == right.Value?.String; 34 | } 35 | 36 | public int GetHashCode(FlexMatch obj) 37 | { 38 | if (ReferenceEquals(obj, null)) 39 | { 40 | return 0; 41 | } 42 | 43 | return obj.Value?.String?.GetHashCode() ?? 0; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: "*" 17 | pull_request: 18 | branches: [ main ] 19 | 20 | jobs: 21 | analyze: 22 | name: Analyze 23 | runs-on: windows-2022 24 | 25 | strategy: 26 | fail-fast: false 27 | 28 | steps: 29 | - name: Checkout repository 30 | uses: actions/checkout@v2 31 | with: 32 | fetch-depth: 0 33 | 34 | - name: Add msbuild to PATH 35 | uses: microsoft/setup-msbuild@v1.0.2 36 | 37 | - name: Initialize CodeQL 38 | uses: github/codeql-action/init@v2 39 | with: 40 | languages: csharp 41 | 42 | - run: | 43 | .\BuildAndTest.cmd -NoFormat -NoTest 44 | 45 | - name: Disk Usage Analytics 46 | run: | 47 | echo "Free space:" 48 | df -h 49 | 50 | - name: Perform CodeQL Analysis 51 | uses: github/codeql-action/analyze@v2 52 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_009.LinkedInCredentialsValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 10 | { 11 | [ValidatorDescriptor("SEC101/009")] 12 | public class LinkedInCredentialsValidator : StaticValidatorBase 13 | { 14 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 15 | { 16 | if (!groups.TryGetNonEmptyValue("id", out FlexMatch id) || 17 | !groups.TryGetNonEmptyValue("secret", out FlexMatch secret)) 18 | { 19 | return ValidationResult.CreateNoMatch(); 20 | } 21 | 22 | var validationResult = new ValidationResult 23 | { 24 | Fingerprint = new Fingerprint 25 | { 26 | Id = id.Value, 27 | Secret = secret.Value, 28 | Platform = nameof(AssetPlatform.LinkedIn), 29 | }, 30 | }; 31 | 32 | return new[] { validationResult }; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_030.GoogleServiceAccountKey.ps1: -------------------------------------------------------------------------------- 1 | # Top 2 taken from https://cloud.google.com/iam/docs/creating-managing-service-account-keys 2 | 3 | { 4 | "type": "service_account", 5 | "project_id": "project-id1", 6 | "private_key_id": "keyId1", 7 | "private_key": "-----BEGIN PRIVATE KEY-----\n11111111\n-----END PRIVATE KEY-----\n", 8 | "client_email": "service-account-email1@server.com", 9 | "client_id": "client-id1", 10 | "auth_uri": "https://accounts.google.com/o/oauth2/auth", 11 | "token_uri": "https://accounts.google.com/o/oauth2/token", 12 | "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", 13 | "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/service-account-email" 14 | } 15 | 16 | { 17 | "name": "projects/project-id1/serviceAccounts/service-account-email2@server.com/keys/keyId2", 18 | "privateKeyType": "TYPE_GOOGLE_CREDENTIALS_FILE", 19 | "privateKeyData": "22222222", 20 | "validAfterTime": "date", 21 | "validBeforeTime": "date", 22 | "keyAlgorithm": "KEY_ALG_RSA_2048" 23 | } 24 | 25 | # Masked from real results 26 | "private_key_id": "0123456789abcdefghijklmnopqrstuvwxyz", "private_key": "-----BEGIN PRIVATE KEY-----\n33333333333333333333three/three\three+three\n-----END PRIVATE KEY-----\n", "client_email": "email@server.stuff.otherstuff.com", "client_id": "333333333333333333333333" -------------------------------------------------------------------------------- /src/RE2.Native/CMake.Original/README.txt: -------------------------------------------------------------------------------- 1 | To get RE2 building in Windows, you use CMake to generate vcxproj files from the 'CMakeLists.txt' file in the RE2 repo. 2 | 3 | https://dfs-minded.com/build-integrate-re2-c-project-windows/ has the original instructions. 4 | 5 | To Build on Windows: 6 | - Install CMAKE - https://cmake.org/download/ 7 | - Run CMake GUI 8 | - 'Source Code': C:\Code\re2 (folder with CMakeLists.txt) 9 | - 'Build': C:\Code\re2\vs 10 | - Click 'Configure'. Pick Visual Studio 15 2017 x64. 11 | - Click 'Generate' 12 | - In Visual Studio, open and build 'C:\Code\re2\vs\RE2.sln' 13 | 14 | To reference: 15 | - Copy and Edit re2.vcxproj. 16 | - Remove with section. 17 | - Remove with to ZERO_CHECK.vcxproj. 18 | - Find and Replace absolute paths with relative ones 19 | - Copy and edit re2.vcxproj.filters; find and replace absolute paths with relative ones 20 | - Add a new C++ console app. 21 | - Add re2.vcxproj as an Existing Project to the solution. 22 | - In your project, open project properties 23 | - References -> Add Reference to RE2. 24 | - C++ -> General -> 'Additional Include Directories'l add RE2 folder (with RE2.h) 25 | - Fix sources which include 're2/stringpiece.h' to no relative path ('stringpiece.h') 26 | 27 | NOTE: Our RE2.vcxproj has other changes to de-duplicate settings and use more consistent output folders. -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Cli/ImportAndAnalyzeOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using CommandLine; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Cli 7 | { 8 | [Verb("import-analyze", HelpText = "Import from and analyze database contents.")] 9 | internal class ImportAndAnalyzeOptions : AnalyzeOptions 10 | { 11 | [Option( 12 | "host", 13 | HelpText = "The database host from which we will retrieve data to scan. " + 14 | "Create AppClientId, AppSecret, and AuthorityId as environment variables.", 15 | Required = true)] 16 | public string Host { get; set; } 17 | 18 | [Option( 19 | "database", 20 | HelpText = "The database from which we will retrieve content to scan.", 21 | Required = true)] 22 | public string Database { get; set; } 23 | 24 | [Option( 25 | "query", 26 | HelpText = "The query that will be used to retrieve content to scan.", 27 | Required = true)] 28 | public string Query { get; set; } 29 | 30 | [Option( 31 | "retain-downloaded-content", 32 | HelpText = "If set to true, the downloaded files won't be deleted.")] 33 | public bool RetainDownloadedContent { get; set; } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/SecurePlaintextSecretsValidators/SEC101_036.MySqlCredentialsValidatorTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | 8 | using Xunit; 9 | 10 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security.Validators 11 | { 12 | /// 13 | /// Testing SEC101/036.MySqlCredentialsValidator 14 | /// 15 | public class MySqlCredentialsValidatorTests 16 | { 17 | [Fact] 18 | public void MySqlCredentialsValidator_Test() 19 | { 20 | string fingerprintText = ""; 21 | if (string.IsNullOrEmpty(fingerprintText)) 22 | { 23 | return; 24 | } 25 | 26 | string message = null; 27 | ResultLevelKind resultLevelKind = default; 28 | var fingerprint = new Fingerprint(fingerprintText); 29 | var keyValuePairs = new Dictionary(); 30 | 31 | var mySqlCredentialsValidator = new MySqlCredentialsValidator(); 32 | mySqlCredentialsValidator.IsValidDynamic(ref fingerprint, 33 | ref message, 34 | keyValuePairs, 35 | ref resultLevelKind); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Cli/ExportSearchDefinitionsOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.IO; 5 | 6 | using CommandLine; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Cli 9 | { 10 | /// 11 | /// export-search-definitions is a command line option that accepts three parameters: input, output, and type. 12 | /// This command transforms the input file in a search definitionformat, which is used in our plugins. 13 | /// 14 | [Verb("export-search-definitions", HelpText = "Export search definitions file from specific formats.")] 15 | internal class ExportSearchDefinitionsOptions 16 | { 17 | [Value( 18 | 0, 19 | HelpText = "Output path for exported search definitions json.", 20 | Required = true)] 21 | public string OutputFilePath { get; set; } 22 | 23 | [Option( 24 | "input", 25 | HelpText = "A path to a file that you want to export as search definition.", 26 | Required = true)] 27 | public string InputFilePath { get; set; } 28 | 29 | [Option( 30 | "type", 31 | HelpText = "Type of the input file (BannedApi or Sal).", 32 | Required = true)] 33 | public string FileType { get; set; } 34 | 35 | public bool Validate() 36 | { 37 | return File.Exists(InputFilePath); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher.Cli/ExportRulesMetatadaCommandTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | using FluentAssertions; 8 | 9 | using Xunit; 10 | 11 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Cli 12 | { 13 | public class ExportRulesMetatadaCommandTests 14 | { 15 | [Fact] 16 | public void ExportRulesMetatadaCommand_InvalidOptions() 17 | { 18 | var tests = new[] 19 | { 20 | new 21 | { 22 | Options = (ExportRulesMetatadaOptions)null 23 | }, 24 | new 25 | { 26 | Options = new ExportRulesMetatadaOptions() 27 | }, 28 | new 29 | { 30 | Options = new ExportRulesMetatadaOptions 31 | { 32 | SearchDefinitionsPaths = new List 33 | { 34 | $@"C:\{Guid.NewGuid()}.txt" 35 | } 36 | } 37 | } 38 | }; 39 | 40 | foreach (var test in tests) 41 | { 42 | var command = new ExportRulesMetatadaCommand(); 43 | int result = command.Run(test.Options); 44 | result.Should().Be(1); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/RE2.Native/RE2.Native.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | 32 | 33 | Source Files 34 | 35 | 36 | Source Files 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/Plugins/Tests.SalModernization/Tests.SalModernization.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $(RootNamespaceBase).Sarif.PatternMatcher.Plugins.SalModernization 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | PreserveNewest 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | all 31 | runtime; build; native; contentfiles; analyzers; buildtransitive 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/RE2.Managed/RE2.LICENSE.txt: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2009 The RE2 Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /src/Plugins/Security/SEC102_003.UrlValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 8 | using Microsoft.RE2.Managed; 9 | 10 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 11 | { 12 | [ValidatorDescriptor("SEC102/003")] 13 | public class UrlValidator : StaticValidatorBase 14 | { 15 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 16 | { 17 | string fullMatchText = groups["0"].Value; 18 | 19 | if (!Uri.TryCreate(fullMatchText, UriKind.Absolute, out Uri uri)) 20 | { 21 | return ValidationResult.CreateNoMatch(); 22 | } 23 | 24 | string query = uri.Query; 25 | string path = uri.PathAndQuery; 26 | 27 | if (path.EndsWith(query)) 28 | { 29 | path = path.Substring(0, path.Length - query.Length); 30 | } 31 | 32 | var validationResult = new ValidationResult 33 | { 34 | Fingerprint = new Fingerprint() 35 | { 36 | Host = uri.Host, 37 | Scheme = uri.Scheme, 38 | Path = path, 39 | Part = query, 40 | Port = uri.Port.ToString(), 41 | }, 42 | }; 43 | 44 | return new[] { validationResult }; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher/SpamExtensionMethods.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.RE2.Managed; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 9 | { 10 | public static class SpamExtensionMethods 11 | { 12 | public static Dictionary ToStringDictionary(this IDictionary dictionary) 13 | { 14 | var stringDictionary = new Dictionary(dictionary.Count); 15 | 16 | foreach (KeyValuePair kv in dictionary) 17 | { 18 | stringDictionary[kv.Key] = kv.Value.Value.String; 19 | } 20 | 21 | return stringDictionary; 22 | } 23 | 24 | public static Dictionary Copy(this IDictionary dictionary) 25 | { 26 | return new Dictionary(dictionary); 27 | } 28 | 29 | public static void AddProperties(this IDictionary dictionary, IDictionary properties) 30 | { 31 | if (properties == null || properties.Count == 0) 32 | { 33 | return; 34 | } 35 | 36 | foreach (KeyValuePair kv in properties) 37 | { 38 | if (!dictionary.ContainsKey(kv.Key)) 39 | { 40 | dictionary[kv.Key] = new FlexMatch() { Value = kv.Value }; 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Cli/AnalyzeDatabaseOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using CommandLine; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Cli.Enums; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Cli 9 | { 10 | [Verb("analyze-database", HelpText = "Analyze a database.")] 11 | internal class AnalyzeDatabaseOptions : AnalyzeOptions 12 | { 13 | [Option( 14 | "connection", 15 | Required = true, 16 | HelpText = "Connection string to data source (Kusto).")] 17 | public string Connection { get; internal set; } 18 | 19 | [Option( 20 | "data-type", 21 | Required = true, 22 | HelpText = "Connection type for the data. Valid inputs: Kusto, SqlLite.")] 23 | public ConnectionType ConnectionType { get; internal set; } 24 | 25 | [Option( 26 | "target", 27 | Required = true, 28 | HelpText = "Data target to analyze against. For example a Kusto query, or SqlLite query.")] 29 | public string Target { get; internal set; } 30 | 31 | [Option( 32 | "batch-size", 33 | Default = 0, 34 | HelpText = "Number of rows of data to process per thread.")] 35 | public int BatchSize { get; internal set; } 36 | 37 | [Option( 38 | "identity", 39 | Required = true, 40 | HelpText = "Column name from your target data query/table that can ordered by for batch processing.")] 41 | public string IdentityColumn { get; internal set; } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Plugins/Security/ReviewPotentiallySensitiveFilesValidators/SEC103_024.MicrosoftSerializedCertificateStoreFileValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security.Utilities; 7 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 8 | using Microsoft.RE2.Managed; 9 | 10 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 11 | { 12 | [ValidatorDescriptor("SEC103/024")] 13 | public class MicrosoftSerializedCertificateStoreFileValidator : StaticValidatorBase 14 | { 15 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 16 | { 17 | string message = string.Empty; 18 | Fingerprint fingerprint = default; 19 | ResultLevelKind resultLevelKind = default; 20 | ValidationState validationState = CertificateHelper.TryLoadCertificateCollection(groups["scanTargetFullPath"].Value, 21 | ref fingerprint, 22 | ref message); 23 | 24 | var validationResult = new ValidationResult 25 | { 26 | Message = message, 27 | Fingerprint = fingerprint, 28 | ResultLevelKind = resultLevelKind, 29 | ValidationState = validationState, 30 | }; 31 | 32 | return new[] { validationResult }; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Sdk/ValidationResult.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.RE2.Managed; 7 | 8 | using Newtonsoft.Json; 9 | using Newtonsoft.Json.Converters; 10 | 11 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk 12 | { 13 | public class ValidationResult 14 | { 15 | public ValidationResult() 16 | { 17 | ValidationState = ValidationState.Unknown; 18 | } 19 | 20 | [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] 21 | public string Message { get; set; } 22 | 23 | public string RawSecretHashSha256 { get; set; } 24 | 25 | public Fingerprint Fingerprint { get; set; } 26 | 27 | [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] 28 | public ResultLevelKind ResultLevelKind { get; set; } 29 | 30 | [JsonConverter(typeof(StringEnumConverter))] 31 | public ValidationState ValidationState { get; set; } 32 | 33 | /// 34 | /// Gets or sets the FlexMatch that describes the result SARIF region. 35 | /// 36 | [JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)] 37 | public FlexMatch RegionFlexMatch { get; set; } 38 | 39 | public static IEnumerable CreateNoMatch() 40 | { 41 | return new[] 42 | { 43 | new ValidationResult 44 | { 45 | ValidationState = ValidationState.NoMatch, 46 | }, 47 | }; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_001.HttpAuthorizationRequestHeader.ps1: -------------------------------------------------------------------------------- 1 | # RestClient example 2 | var client = new RestClient("https://example.com"); 3 | var request = new RestRequest(Method.GET); 4 | request.AddHeader("Authorization", "Basic SomeAuthorizationKey1111111"); 5 | 6 | var client = new RestClient("https://example.com?some=parameters&that=should&appear=inresults") 7 | var request = new RestRequest(Method.GET); 8 | request.AddHeader("Authorization", "Basic SomeAuthorizationKey2222222"); 9 | 10 | # cURL 11 | curl --location --request GET 'https://example.com' \ 12 | --header 'Authorization: Basic SomeAuthorizationKey3333333=' \ 13 | 14 | # This should not get caught, since it will drop the last slash 15 | # and would be equal to the first example. 16 | var client = new RestClient("https://example.com/") 17 | var request = new RestRequest(Method.GET); 18 | request.AddHeader("Authorization", "Basic SomeAuthorizationKey4444444"); 19 | 20 | # This should not get caught, since it would surpass the length 21 | # between url and authorization 22 | var client = new RestClient("https://example.com/") 23 | var request = new RestRequest(Method.GET); 24 | var text = "more text to surpass the size."; 25 | request.AddHeader("Authorization", "Basic SomeAuthorizationKey5555555"); 26 | 27 | 28 | 29 | GET http://we.want.that.site.com/16 HTTP/1.1 30 | Host: we.want.that.site.com 31 | Proxy-Authorization: Basic 6666666b29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29vb29uZw== 32 | Accept: */* 33 | Proxy-Connection: Keep-Alive 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher.Cli/Test.UnitTests.Sarif.PatternMatcher.Cli.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $(RootNamespaceBase).Sarif.PatternMatcher.Cli 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | PreserveNewest 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | PreserveNewest 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | all 42 | runtime; build; native; contentfiles; analyzers; buildtransitive 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to sarif-pattern-matcher 2 | 3 | ## Development Environment 4 | 5 | You can contribute to this project from a Windows, macOS or Linux machine. 6 | 7 | On all platforms, the minimum requirements are: 8 | 9 | * Git client and command line tools. 10 | * .NET Core 3.1+ and .NET 6.0 11 | 12 | ### Windows 13 | 14 | * Visual Studio 2022, any edition 15 | * In the Visual Studio Installer, install the following: 16 | * Workloads 17 | * .NET desktop development 18 | * Desktop development with C++ 19 | * Individual components 20 | * C++ x64/x86 Spectre-mitigated libs (Latest) 21 | 22 | ## Style Guide 23 | 24 | This project includes a 25 | [`.editorconfig`](https://github.com/microsoft/sarif-pattern-matcher/blob/main/src/.editorconfig) 26 | file which is supported by all the IDEs/editor mentioned above. It works with 27 | the IDE/editor only and does not affect the actual build of the project. 28 | 29 | ## How to start 30 | 31 | Clone the repository with the command: 32 | 33 | ```bat 34 | git clone https://github.com/microsoft/sarif-pattern-matcher.git 35 | ``` 36 | 37 | Then, update the submodules: 38 | 39 | ```bat 40 | git submodule update --init --recursive 41 | ``` 42 | 43 | To build the solution you can: 44 | 45 | * Open `Developer Command Prompt for VS 2019` and run the following: 46 | 47 | ```bat 48 | .\BuildAndTest.cmd 49 | ``` 50 | 51 | * Use Visual Studio: 52 | 53 | 1. Open the solution `src\RE2.Native.sln` and build. 54 | 2. Open the solution `src\SarifPatternMatcher.sln` and build. 55 | 56 | ## Troubleshooting First Commit 57 | If you are having trouble with your first commit or push to the GitHub, first please confirm with your repository admin to ensure you have write permissions. 58 | Then remove and re-add all accounts in Visual Studio Account Settings Menu. -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher.Cli/TestValidators/StaticAndDynamicValidatorsExistForMatchExpressionValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Cli.TestValidators 10 | { 11 | [ValidatorDescriptor(Id)] 12 | internal class StaticAndDynamicValidatorsExistForMatchExpressionValidator : DynamicValidatorBase 13 | { 14 | internal const string Id = "TEST001/003"; 15 | 16 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 17 | { 18 | string secret = groups["0"].Value; 19 | 20 | var validationResult = new ValidationResult 21 | { 22 | Fingerprint = new Fingerprint 23 | { 24 | Platform = nameof(AssetPlatform.Unknown), 25 | Secret = secret, 26 | }, 27 | ValidationState = ValidationState.Unknown, 28 | }; 29 | 30 | return new[] { validationResult }; 31 | } 32 | 33 | protected override ValidationState IsValidDynamicHelper(ref Fingerprint fingerprint, 34 | ref string message, 35 | IDictionary options, 36 | ref ResultLevelKind resultLevelKind) 37 | { 38 | return ValidationState.Authorized; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/RE2.Native/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ======================================================================== 2 | CONSOLE APPLICATION : [!output PROJECT_NAME] Project Overview 3 | ======================================================================== 4 | 5 | AppWizard has created this [!output PROJECT_NAME] application for you. 6 | 7 | This file contains a summary of what you will find in each of the files that 8 | make up your [!output PROJECT_NAME] application. 9 | 10 | 11 | This is the main project file for VC++ projects generated using an Application Wizard. 12 | It contains information about the version of Visual C++ that generated the file, and 13 | information about the platforms, configurations, and project features selected with the 14 | Application Wizard. 15 | 16 | This is the filters file for VC++ projects generated using an Application Wizard. 17 | It contains information about the association between the files in your project 18 | and the filters. This association is used in the IDE to show grouping of files with 19 | similar extensions under a specific node (for e.g. ".cpp" files are associated with the 20 | "Source Files" filter). 21 | 22 | This is the main application source file. 23 | 24 | ///////////////////////////////////////////////////////////////////////////// 25 | Other standard files: 26 | 27 | StdAfx.h, StdAfx.cpp 28 | These files are used to build a precompiled header (PCH) file 29 | named [!output PROJECT_NAME].pch and a precompiled types file named StdAfx.obj. 30 | 31 | ///////////////////////////////////////////////////////////////////////////// 32 | Other notes: 33 | 34 | AppWizard uses "TODO:" comments to indicate parts of the source code you 35 | should add to or customize. 36 | 37 | ///////////////////////////////////////////////////////////////////////////// 38 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/ValidatorBaseTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | using FluentAssertions; 8 | 9 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 10 | 11 | using Xunit; 12 | 13 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 14 | { 15 | public class ValidatorBaseTests : ValidatorBase 16 | { 17 | [Fact] 18 | public void ValidatorBase_ParseValue() 19 | { 20 | ValidatorBase.ParseValue(null).Should().BeNull(); 21 | ValidatorBase.ParseValue(string.Empty).Should().BeNullOrWhiteSpace(); 22 | 23 | var strings = new List 24 | { 25 | "some-value", 26 | "some-key=some-value", 27 | " some-value ", 28 | "some-value ", 29 | " some-value", 30 | "\tsome-value", 31 | "some-value\t" 32 | }; 33 | 34 | foreach (string text in strings) 35 | { 36 | ValidatorBase.ParseValue(text).Should().Be("some-value"); 37 | } 38 | } 39 | 40 | [Fact] 41 | public void ScanIdentityGuid_MustBeGuid() 42 | { 43 | Assert.Throws(() => ScanIdentityGuid = "notGuid"); 44 | 45 | string firstGuidValue = ScanIdentityGuid; 46 | ScanIdentityGuid.Should().NotBeNullOrEmpty(); 47 | ScanIdentityGuid.Should().Be(firstGuidValue); 48 | 49 | var guid = Guid.NewGuid(); 50 | ScanIdentityGuid = $"{guid}"; 51 | ScanIdentityGuid.Should().Be($"{guid}"); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/SecurePlaintextSecretsValidators/SEC101_037.SqlCredentialsValidatorTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 7 | using Microsoft.RE2.Managed; 8 | 9 | using Xunit; 10 | 11 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security.Validators 12 | { 13 | /// 14 | /// Testing SEC101/037.SqlCredentialsValidator 15 | /// 16 | public class SqlCredentialsValidatorTests 17 | { 18 | [Fact] 19 | public void SqlCredentialsValidatorTests_Test() 20 | { 21 | string fingerprintText = "[host=server][id=account][resource=database][secret=password]"; 22 | string message = null; 23 | ResultLevelKind resultLevelKind = default; 24 | var fingerprint = new Fingerprint(fingerprintText); 25 | var keyValuePairs = new Dictionary(); 26 | 27 | ValidatorBase.RegexInstance = IronRE2Regex.Instance; 28 | var sqlCredentialsValidator = new SqlCredentialsValidator(); 29 | ValidationState actualValidationState = sqlCredentialsValidator.IsValidDynamic(ref fingerprint, 30 | ref message, 31 | keyValuePairs, 32 | ref resultLevelKind); 33 | Assert.True(actualValidationState == ValidationState.Unknown || actualValidationState == ValidationState.UnknownHost); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Plugins/Tests.AzureDevOpsConfiguration/Tests.AzureDevOpsConfiguration.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $(RootNamespaceBase).Sarif.PatternMatcher.Plugins.AzureDevOpsConfiguration 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | PreserveNewest 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | all 36 | runtime; build; native; contentfiles; analyzers; buildtransitive 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/Tests.Security.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | $(RootNamespaceBase).Sarif.PatternMatcher.Plugins.Security 8 | 9 | 10 | 11 | 12 | PreserveNewest 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | all 38 | runtime; build; native; contentfiles; analyzers; buildtransitive 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/Plugins/Security/ReviewPotentiallySensitiveDataValidators/SEC102_001.EmailAddressValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Net.Mail; 6 | 7 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 8 | using Microsoft.RE2.Managed; 9 | 10 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 11 | { 12 | [ValidatorDescriptor("SEC102/001")] 13 | public class EmailAddressValidator : StaticValidatorBase 14 | { 15 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 16 | { 17 | if (!groups.TryGetNonEmptyValue("id", out FlexMatch id) || 18 | !groups.TryGetNonEmptyValue("host", out FlexMatch host)) 19 | { 20 | return ValidationResult.CreateNoMatch(); 21 | } 22 | 23 | string candidateAddress = $"{id.Value}@{host.Value}"; 24 | 25 | try 26 | { 27 | var actualAddress = new MailAddress(candidateAddress); 28 | if (actualAddress.Address != candidateAddress) 29 | { 30 | return ValidationResult.CreateNoMatch(); 31 | } 32 | 33 | var validationResult = new ValidationResult 34 | { 35 | Fingerprint = new Fingerprint() 36 | { 37 | Id = id.Value, 38 | Host = host.Value, 39 | }, 40 | }; 41 | 42 | return new[] { validationResult }; 43 | } 44 | catch 45 | { 46 | return ValidationResult.CreateNoMatch(); 47 | } 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Sdk/SharedUtilities.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk 7 | { 8 | public static class SharedUtilities 9 | { 10 | public static void PopulateAssetFingerprint(List azureHosts, string host, ref Fingerprint fingerprint) 11 | { 12 | if (GetDatabasePlatformFromHost(azureHosts, host, out _) != nameof(AssetPlatform.Azure)) 13 | { 14 | fingerprint.Platform = nameof(AssetPlatform.SqlOnPremise); 15 | return; 16 | } 17 | 18 | fingerprint.Part = "servers"; 19 | fingerprint.Platform = nameof(AssetPlatform.Azure); 20 | } 21 | 22 | private static string GetDatabasePlatformFromHost(List platformHosts, string host, out string resource) 23 | { 24 | resource = null; 25 | 26 | foreach (string item in platformHosts) 27 | { 28 | string result = ExtractResource(item, host, out resource); 29 | if (!string.IsNullOrEmpty(result)) 30 | { 31 | return result; 32 | } 33 | } 34 | 35 | return nameof(AssetPlatform.SqlOnPremise); 36 | } 37 | 38 | private static string ExtractResource(string pattern, string host, out string resource) 39 | { 40 | resource = null; 41 | 42 | int indexOf = host.IndexOf(pattern); 43 | if (indexOf >= 0) 44 | { 45 | resource = host.Substring(0, indexOf); 46 | return nameof(AssetPlatform.Azure); 47 | } 48 | 49 | return string.Empty; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/Plugins/AzureDevOpsConfiguration/AzureDevOpsConfiguration.SharedStrings.txt: -------------------------------------------------------------------------------- 1 | # 2 | # This file contains key values pairs which are used to expand variable references in 3 | # the JSON-based regex pattern definition files. This is useful both to share common 4 | # regex patterns across multiple rules but also to avoid the complexities of escaping 5 | # JSON string literals. The strings below are directly testable in web sites such as 6 | # reg101.com. 7 | # 8 | # Shared strings can be assembled even within this file as long as any shared pattern 9 | # in a strings only contains variables which are defined earlier in the file. So, 10 | # a pattern like this is ok (but these lines in reverse order are not). 11 | # 12 | # $MyExample=[a-z] 13 | # $MyExpandedExample=($MyExample|[0-9]) 14 | # 15 | # Blank lines are ignored when parsing, as are lines that begin with a '#' character. 16 | # Leading spaces are trimmed at parse time, allowing for indentation. 17 | 18 | # Common patterns for file allow and deny lists. 19 | # 20 | $BuildDefinitionFiles=(?i)(^https?:\/\/dev\.azure\.com).*(\/_apis\/build\/definitions\/)|(azc101\.builddefinition\..*json$) 21 | $ServiceConnectionFiles=(?i)(^https?:\/\/dev\.azure\.com).*(\/_settings\/adminservices)|(azc102[_\d]*\.serviceconnection\..*json$) 22 | 23 | $AdoOrganizationName=(?i)"_accountName"\s*:\s*"(?P.*?)" 24 | $AdoProjectName=(?i)"_projectId"\s*:\s*"(?P.*?)" 25 | 26 | $AZC101.BuildDefinitionEntityType=(?i)(?P"uri"\s*:\s*"vstfs:///Build/Definition/) 27 | $AZC102.ServiceConnectionEntityType=(?i)(?P"serviceEndpointProjectReferences") 28 | $AZC102.ServiceConnectionId=(?iU)^{[\s\S]*"id"\s*:\s*"(?P[[0-9A-F]{8}[-]?(?:[0-9A-F]{4}[-]?){3}[0-9A-F]{12})" 29 | 30 | $AZC101/240.PullRequestTriggerType=(?i)(?P"triggerType"\s*:\s*"pullRequest") 31 | $AZC101/240.ForkedEnabled=(?i)(?P"forks"\s*:\s*{\s*"enabled"\s*:\s*true\s*,\s*"allowSecrets"\s*:\s*true\s*}) 32 | $AZC102/150.AzureClassicType=(?i)(?P"type"\s*:\s*"azure") 33 | -------------------------------------------------------------------------------- /src/Plugins/Security/SecurePlaintextSecretsValidators/SEC101_017.NpmLegacyAuthorTokenValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Net.Http; 6 | 7 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 8 | using Microsoft.RE2.Managed; 9 | 10 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security 11 | { 12 | [ValidatorDescriptor("SEC101/017")] 13 | public class NpmLegacyAuthorTokenValidator : DynamicValidatorBase 14 | { 15 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 16 | { 17 | FlexMatch secret = groups["secret"]; 18 | 19 | var validationResult = new ValidationResult 20 | { 21 | Fingerprint = new Fingerprint 22 | { 23 | Secret = secret.Value, 24 | Platform = nameof(AssetPlatform.Npm), 25 | }, 26 | }; 27 | 28 | return new[] { validationResult }; 29 | } 30 | 31 | protected override ValidationState IsValidDynamicHelper(ref Fingerprint fingerprint, 32 | ref string message, 33 | IDictionary options, 34 | ref ResultLevelKind resultLevelKind) 35 | { 36 | HttpClient client = CreateOrRetrieveCachedHttpClient(); 37 | 38 | return NpmLegacyAuthorTokenHelper.ValidateTokens(ref fingerprint, 39 | ref message, 40 | ref resultLevelKind, 41 | client); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher.Function/Test.UnitTests.Sarif.PatternMatcher.Function.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | all 26 | runtime; build; native; contentfiles; analyzers; buildtransitive 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/Plugins/Tests.Security/TestData/SecurePlaintextSecrets/Inputs/SEC101_043.NuGetCredentials.ps1: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | \nstuff\n<\/packageSources>\n 34 | \n \n \n 35 | 36 | -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher.Function/TestHelper.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | using System.IO; 6 | 7 | using Microsoft.AspNetCore.Http; 8 | using Microsoft.Azure.WebJobs; 9 | using Microsoft.Extensions.Primitives; 10 | 11 | using Moq; 12 | 13 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Function 14 | { 15 | public static class TestHelper 16 | { 17 | public static string SampleCode = @" 18 | namespace AnalysisTestProject2 19 | { 20 | internal class Class4 21 | { 22 | } 23 | } 24 | "; 25 | 26 | public static HttpRequest MockAnalyzeFunctionRequest(string fileName, string fileContent) 27 | { 28 | var formData = new Dictionary 29 | { 30 | { FunctionConstants.FileNamePropertyName, fileName }, 31 | { FunctionConstants.FileContentPropertyName, fileContent } 32 | }; 33 | return HttpRequestSetup(formData); 34 | } 35 | 36 | public static HttpRequest HttpRequestSetup(Dictionary formData) 37 | { 38 | var requestMock = new Mock(); 39 | requestMock.Setup(req => req.Form).Returns(new FormCollection(formData)); 40 | return requestMock.Object; 41 | } 42 | 43 | public static ExecutionContext ContextSetup() 44 | { 45 | // no need to mock 46 | return new ExecutionContext { FunctionDirectory = Path.GetFullPath("." + Path.DirectorySeparatorChar) }; 47 | } 48 | 49 | public static string GetTestResourceContent(string fileName) 50 | { 51 | string filePath = Path.Combine("TestData", fileName); 52 | return File.ReadAllText(filePath); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher/Sarif.PatternMatcher.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Sarif Pattern Matcher Library 8 | A general pattern matching engine that persist results to SARIF. 9 | $(RootNamespaceBase).Sarif.PatternMatcher 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | PreserveNewest 27 | 28 | 29 | True 30 | True 31 | SpamResources.resx 32 | 33 | 34 | 35 | 36 | 37 | ResXFileCodeGenerator 38 | SpamResources.Designer.cs 39 | 40 | 41 | 42 | 43 | 44 | all 45 | runtime; build; native; contentfiles; analyzers 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Cli/Sarif.PatternMatcher.Cli.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Exe 8 | Sarif.PatternMatcher.Cli 9 | Sarif.PatternMatcher.Cli 10 | $(RootNamespaceBase).Sarif.PatternMatcher.Cli 11 | true 12 | 13 | 14 | 15 | Sarif Pattern Matcher Cli 16 | A general pattern matcher that persists results to the SARIF format. 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | false 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | PreserveNewest 41 | 42 | 43 | 44 | 45 | 46 | all 47 | runtime; build; native; contentfiles; analyzers 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/Plugins/AzureDevOpsConfiguration/AZC101.BuildDefinitionSecurity.json: -------------------------------------------------------------------------------- 1 | { 2 | "ValidatorsAssemblyName": "AzureDevOpsConfiguration.dll", 3 | "SharedStringsFileName": "AzureDevOpsConfiguration.SharedStrings.txt", 4 | "ExtensionName": "SecureAzureDevOps", 5 | "Guid": "183f9c88-1424-4f6c-a8a5-cd59c0bdc312", 6 | "Definitions": [ 7 | { 8 | "Id": "AZC101", 9 | "Name": "BuildDefinitionShouldBeSecure", 10 | "Level": "Error", 11 | "Description": "Make sure build definitions in AzureDevOps are secure", 12 | "MatchExpressions": [ 13 | { 14 | "Id": "AZC101/240", 15 | "Name": "DontMakeSecretsAvailableToForkedBuilds", 16 | "Message": "[Build Definition Id:{0:scanTarget}]({1:adoDomain}/{2:org}/{3:project}/_build/definitionId={0:scanTarget}) in organization '{2:org}' project '{3:project}' was found {4:issueDesc} {5:description} {6:recommendation}.", 17 | "Description": "Do not make secrets available to builds for fork of public repository.", 18 | "IntrafileRegexes": [ 19 | "$AZC101.BuildDefinitionEntityType", 20 | "$AZC101/240.PullRequestTriggerType", 21 | "$AZC101/240.ForkedEnabled", 22 | "$AdoOrganizationName", 23 | "$AdoProjectName" 24 | ], 25 | "MessageArguments": { 26 | "adoDomain": "https://dev.azure.com", 27 | "issueDesc": "its build pipeline secrets available for builds of forks.", 28 | "description": "For GitHub public repositories, it is possible that people from outside the organization can create forks and run builds on the forked repo. In such a case, if this setting is wrongly left enabled, outsiders can get access to build pipeline secrets that were meant to be internal.", 29 | "recommendation": "Recommendation: 1. Navigate to the build pipeline using resource link --> 2. Triggers --> 3. Pull request validation --> 4. Forks --> 5. Uncheck 'Make secrets available to builds of forks'" 30 | }, 31 | "HelpUri": "https://docs.microsoft.com/en-us/azure/devops/pipelines/repos/github?view=azure-devops&tabs=yaml#important-security-considerations" 32 | } 33 | ] 34 | } 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /src/Plugins/Security/Utilities/FilteringHelpers.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Plugins.Security.Utilities 8 | { 9 | public static class FilteringHelpers 10 | { 11 | public static readonly HashSet LocalhostList = new HashSet(StringComparer.OrdinalIgnoreCase) 12 | { 13 | "localhost", 14 | "(local)", 15 | "127.0.0.1", 16 | ".", 17 | }; 18 | 19 | public static string StandardizeLocalhostName(string host) 20 | { 21 | return LocalhostList.Contains(host) 22 | ? "localhost" 23 | : host; 24 | } 25 | 26 | public static bool LikelyPowershellVariable(string input) 27 | { 28 | if (input.Length < 4) 29 | { 30 | // Not enough space for a variable name in the string 31 | return false; 32 | } 33 | 34 | if (input[0] != '$') 35 | { 36 | return false; 37 | } 38 | 39 | if (input[1] != '(') 40 | { 41 | return false; 42 | } 43 | 44 | if (input[input.Length - 1] != ')') 45 | { 46 | return false; 47 | } 48 | 49 | return true; 50 | } 51 | 52 | public static bool PasswordIsInCommonVariableContext(string secret) 53 | { 54 | var passwordContextList = new List> 55 | { 56 | new Tuple("{", "}"), 57 | new Tuple("$(", ")"), 58 | }; 59 | 60 | foreach (Tuple tuplePair in passwordContextList) 61 | { 62 | if (secret.StartsWith(tuplePair.Item1)) 63 | { 64 | return secret.EndsWith(tuplePair.Item2); 65 | } 66 | } 67 | 68 | return false; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher/TestLogger.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 7 | { 8 | public class TestLogger : IAnalysisLogger 9 | { 10 | public IList ConfigurationNotifications { get; set; } 11 | public IList ToolNotifications { get; set; } 12 | public ISet Rules { get; set; } 13 | public IList Results { get; set; } 14 | 15 | public bool NoNotificationsFired 16 | { 17 | get => ConfigurationNotifications == null && ToolNotifications == null; 18 | } 19 | 20 | public bool NothingFired 21 | { 22 | get => Results == null && NoNotificationsFired; 23 | } 24 | 25 | public FileRegionsCache FileRegionsCache { get; set; } 26 | 27 | public void AnalysisStarted() 28 | { 29 | } 30 | 31 | public void AnalysisStopped(RuntimeConditions runtimeConditions) 32 | { 33 | } 34 | 35 | public void AnalyzingTarget(IAnalysisContext context) 36 | { 37 | } 38 | 39 | public void TargetAnalyzed(IAnalysisContext context) 40 | { 41 | } 42 | 43 | public void Log(ReportingDescriptor rule, Result result, int? extensionIndex) 44 | { 45 | Results ??= new List(); 46 | Results.Add(result); 47 | 48 | Rules ??= new HashSet(ReportingDescriptor.ValueComparer); 49 | Rules.Add(rule); 50 | } 51 | 52 | public void LogConfigurationNotification(Notification notification) 53 | { 54 | ConfigurationNotifications ??= new List(); 55 | ConfigurationNotifications.Add(notification); 56 | } 57 | 58 | public void LogToolNotification(Notification notification, ReportingDescriptor _) 59 | { 60 | ToolNotifications ??= new List(); 61 | ToolNotifications.Add(notification); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Sdk/ValidationState.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk 5 | { 6 | public enum ValidationState 7 | { 8 | /// 9 | /// A default value that reflects an uninitialized state, 10 | /// (i.e., no useful validation state is available). 11 | /// 12 | None = 0, 13 | 14 | /// 15 | /// Validator not found. 16 | /// 17 | ValidatorNotFound, 18 | 19 | /// 20 | /// A validator for the current matched pattern returned 21 | /// an unrecognized state when asked to validate. 22 | /// 23 | ValidatorReturnedIllegalValidationState, 24 | 25 | /// 26 | /// Pattern isn't actually a match for secret type. 27 | /// 28 | NoMatch, 29 | 30 | /// 31 | /// The validity of the secret can't be determined. 32 | /// 33 | Unknown, 34 | 35 | /// 36 | /// The secret is not authorized for access. 37 | /// 38 | Unauthorized, 39 | 40 | /// 41 | /// The secret is expired. 42 | /// 43 | Expired, 44 | 45 | /// 46 | /// The file or resource is password-protected. 47 | /// 48 | PasswordProtected, 49 | 50 | /// 51 | /// The host is unknown. 52 | /// 53 | UnknownHost, 54 | 55 | /// 56 | /// Pattern is a match and the secret is invalid for all 57 | /// all authorities configured for validation (e.g., it 58 | /// is expired). The secret may be valid for an authority 59 | /// that wasn't consulted. 60 | /// 61 | InvalidForConsultedAuthorities, 62 | 63 | /// 64 | /// Pattern is a match and the secret is valid. 65 | /// The result should be reported as an error. 66 | /// 67 | Authorized, 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher.Sdk/DynamicValidatorBase.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk 8 | { 9 | public abstract class DynamicValidatorBase : StaticValidatorBase 10 | { 11 | public virtual bool DynamicAnalysisImplemented => true; 12 | 13 | public ValidationState IsValidDynamic(ref Fingerprint fingerprint, 14 | ref string message, 15 | IDictionary options, 16 | ref ResultLevelKind resultLevelKind) 17 | { 18 | resultLevelKind = default; 19 | 20 | if (shouldUseDynamicCache && 21 | FingerprintToResultCache.TryGetValue(fingerprint, out Tuple result)) 22 | { 23 | message = result.Item3; 24 | resultLevelKind = result.Item2; 25 | return result.Item1; 26 | } 27 | 28 | ValidationState validationState = IsValidDynamicHelper(ref fingerprint, 29 | ref message, 30 | options, 31 | ref resultLevelKind); 32 | 33 | FingerprintToResultCache[fingerprint] = 34 | new Tuple(validationState, resultLevelKind, message); 35 | 36 | return validationState; 37 | } 38 | 39 | protected virtual ValidationState IsValidDynamicHelper(ref Fingerprint fingerprint, 40 | ref string message, 41 | IDictionary options, 42 | ref ResultLevelKind resultLevelKind) 43 | { 44 | return ValidationState.NoMatch; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Test.UnitTests.Sarif.PatternMatcher/TestRuleValidator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | using Microsoft.CodeAnalysis.Sarif.PatternMatcher.Sdk; 8 | using Microsoft.RE2.Managed; 9 | 10 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 11 | { 12 | [ValidatorDescriptor(SpamTestRule.TestRuleId)] 13 | public class TestRuleValidator : DynamicValidatorBase 14 | { 15 | public delegate IEnumerable IsValidStaticDelegate(IDictionary groups); 16 | 17 | public delegate ValidationState IsValidDynamicDelegate(ref Fingerprint fingerprint, 18 | ref string message, 19 | IDictionary options, 20 | ref ResultLevelKind resultLevelKind); 21 | 22 | [ThreadStatic] 23 | public static IsValidStaticDelegate OverrideIsValidStatic; 24 | 25 | [ThreadStatic] 26 | public static IsValidDynamicDelegate OverrideIsValidDynamic; 27 | 28 | protected override IEnumerable IsValidStaticHelper(IDictionary groups) 29 | { 30 | if (OverrideIsValidStatic == null) 31 | { 32 | return null; 33 | } 34 | 35 | return OverrideIsValidStatic(groups); 36 | } 37 | 38 | protected override ValidationState IsValidDynamicHelper(ref Fingerprint fingerprint, 39 | ref string message, 40 | IDictionary options, 41 | ref ResultLevelKind resultLevelKind) 42 | { 43 | if (OverrideIsValidDynamic == null) 44 | { 45 | return 0; 46 | } 47 | 48 | return OverrideIsValidDynamic(ref fingerprint, ref message, options, ref resultLevelKind); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher/AnalyzeOptions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using CommandLine; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.Driver; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 9 | { 10 | [Verb("analyze")] 11 | public class AnalyzeOptions : AnalyzeOptionsBase 12 | { 13 | [Option( 14 | "vcp", 15 | Separator = ';', 16 | HelpText = "A serialized JSON version control details object to persist to the output file.")] 17 | public string VersionControlProvenance { get; set; } 18 | 19 | [Option( 20 | "dynamic-validation", 21 | HelpText = "Enable dynamic validations, if any (may compromise " + 22 | "performance and/or result in calls across the network).")] 23 | public bool? DynamicValidation { get; set; } 24 | 25 | [Option( 26 | "disable-dynamic-validation-caching", 27 | HelpText = "Disable caching from dynamic validation.")] 28 | public bool? DisableDynamicValidationCaching { get; set; } 29 | 30 | [Option( 31 | "enhanced-reporting", 32 | HelpText = "Enable enhanced reporting provided by dynamic validators (when --dynamic-validation is also enabled).")] 33 | public bool? EnhancedReporting { get; set; } 34 | 35 | [Option( 36 | "retry", 37 | HelpText = "Enable retry connection if enabled.")] 38 | public bool? Retry { get; set; } 39 | 40 | [Option( 41 | "max-memory-in-kb", 42 | HelpText = "The maximum memory (in kilobytes) that can be used for RE2.", 43 | Default = -1)] 44 | public long MaxMemoryInKilobytes { get; set; } 45 | 46 | [Option( 47 | "redact-secrets", 48 | HelpText = "Redact sensitive credential components from log files.")] 49 | public bool? RedactSecrets { get; set; } 50 | 51 | [Option( 52 | "engine", 53 | HelpText = "The pattern matching engine to use for analysis. One of RE2, DotNet, or CachedDotNet.")] 54 | public RegexEngine RegexEngine { get; set; } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Test.UnitTests.RE2.Managed/FlexMatchValueComparerTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using FluentAssertions; 7 | 8 | using Xunit; 9 | 10 | namespace Microsoft.RE2.Managed 11 | { 12 | public class FlexMatchValueComparerTests 13 | { 14 | [Fact] 15 | public void FlexMatchValueComparer_ComparerInSet() 16 | { 17 | var hashSet = new HashSet(); 18 | hashSet.Add(new FlexMatch { Value = "1" }); 19 | hashSet.Add(new FlexMatch { Value = "1" }); 20 | hashSet.Count.Should().Be(2); 21 | 22 | hashSet = new HashSet(FlexMatchValueComparer.Instance); 23 | hashSet.Add(new FlexMatch { Value = "1" }); 24 | hashSet.Add(new FlexMatch { Value = "1" }); 25 | hashSet.Count.Should().Be(1); 26 | } 27 | 28 | [Fact] 29 | public void FlexMatchValuComparer_Equality() 30 | { 31 | var flex1 = new FlexMatch { Value = "1" }; 32 | var flex2 = new FlexMatch { Value = "1" }; 33 | var flex3 = new FlexMatch { Value = "2" }; 34 | 35 | FlexMatchValueComparer comparer = FlexMatchValueComparer.Instance; 36 | comparer.Equals(null, null).Should().BeTrue(); 37 | comparer.Equals(flex1, flex1).Should().BeTrue(); 38 | comparer.Equals(flex1, flex2).Should().BeTrue(); 39 | comparer.Equals(flex1, null).Should().BeFalse(); 40 | comparer.Equals(null, flex1).Should().BeFalse(); 41 | comparer.Equals(flex1, flex3).Should().BeFalse(); 42 | } 43 | 44 | [Fact] 45 | public void FlexMatchValuComparer_GetHashCode() 46 | { 47 | FlexMatch flex = null; 48 | FlexMatchValueComparer comparer = FlexMatchValueComparer.Instance; 49 | comparer.GetHashCode(flex).Should().Be(0); 50 | 51 | flex = new FlexMatch(); 52 | comparer.GetHashCode(flex).Should().Be(0); 53 | 54 | flex = new FlexMatch { Value = "1" }; 55 | comparer.GetHashCode(flex).Should().Be("1".GetHashCode()); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Plugins/Security/SEC102.ReviewPotentiallySensitiveData.json: -------------------------------------------------------------------------------- 1 | { 2 | "ValidatorsAssemblyName": "Security.dll", 3 | "SharedStringsFileName": "Security.SharedStrings.txt", 4 | "ExtensionName": "ReviewPotentiallySensitiveData", 5 | "Guid": "dad7661b-34d6-4052-87b4-e234d9aae66b", 6 | "Definitions": [ 7 | { 8 | "Id": "SEC102", 9 | "Name": "ReviewPotentiallySensitiveData", 10 | "Level": "Note", 11 | "FileNameAllowRegex": "(?i)\\.(azure|bat|c|cmd|config|cpp|cs|cscfg|definitions|dtsx|h|hxx|hpp|ini|java|jsx?|json|keys|kt|loadtest|m|md|php|properties|ps1|psm1|pubxml|py|resx|sample|sql|ste|swift|test|tsx?|txt|waz|xml)$", 12 | "Description": "Review exposed potentially sensitive data, such as service principal names, social security numbers, etc.", 13 | "Message": "'{0:truncatedSecret}' is an apparent {1:dataKind}.", 14 | "MatchExpressions": [ 15 | { 16 | "Id": "SEC102/001", 17 | "Name": "ReviewPotentiallySensitiveData/EmailAddress", 18 | "ContentsRegex": "\\b(?i)(?P[0-9a-z._%+-]*[0-9a-z]+)@(?P[0-9a-z]+[0-9a-z.-]*\\.[0-9a-z]{2,})", 19 | "Message": "'{0:id}@{1:host}' is an apparent {2:dataKind}.", 20 | "MessageArguments": { "dataKind": "email address" }, 21 | "Notes": [ "This will not catch every possible email address. According to https://www.regular-expressions.info/email.html it is not reasonable to expect to do so. The formal RFC definition of an email address includes things which some systems can't support, such as double quotes, spaces, and other special characters. What we have here should capture about 99% of email addresses in use today." ] 22 | }, 23 | { 24 | "Id": "SEC102/002", 25 | "Name": "ReviewPotentiallySensitiveData/SocialSecurityNumber", 26 | "ContentsRegex": "\\b(?P(?P[0-9]{3}-[0-9]{2}-[0-9]{4}))\\b", 27 | "MessageArguments": { "dataKind": "social security number" } 28 | }, 29 | { 30 | "Id": "SEC102/003", 31 | "Name": "ReviewPotentiallySensitiveData/Url", 32 | "FileNameAllowRegex": "(?i)(\\.cs|\\.cpp|\\.ini|\\.js|\\.ps1)$", 33 | "ContentsRegex": "$SEC102/003.Url", 34 | "Message": "'{0:url}' is an apparent URL." 35 | } 36 | ] 37 | } 38 | ] 39 | } -------------------------------------------------------------------------------- /src/Plugins/SalModernization/SalModernization.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | netstandard2.0;net472 9 | true 10 | $(RootNamespaceBase).Sarif.PatternMatcher.Plugins.SalModernization 11 | Sarif.PatternMatcher.SalModernization 12 | 13 | 14 | 15 | 16 | build\ 17 | 18 | 19 | PreserveNewest 20 | 21 | 22 | PreserveNewest 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | all 33 | runtime; build; native; contentfiles; analyzers 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/Sarif.PatternMatcher/MatchExpression.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | using Microsoft.CodeAnalysis.Sarif.Driver; 7 | 8 | namespace Microsoft.CodeAnalysis.Sarif.PatternMatcher 9 | { 10 | public class MatchExpression 11 | { 12 | public IList RegexMetadata { get; set; } 13 | 14 | public List SniffLiterals { get; set; } 15 | 16 | public IList IntrafileRegexes { get; set; } 17 | 18 | public IList SingleLineRegexes { get; set; } 19 | 20 | public string Id { get; set; } 21 | 22 | public string SubId { get; set; } 23 | 24 | public string Index { get; set; } 25 | 26 | public string Name { get; set; } 27 | 28 | public string DeprecatedName { get; set; } 29 | 30 | public string HelpUri { get; set; } 31 | 32 | public string Message { get; set; } 33 | 34 | public RuleEnabledState RuleEnabledState { get; set; } 35 | 36 | public FailureLevel Level { get; set; } 37 | 38 | public ResultKind Kind { get; set; } 39 | 40 | public string Description { get; set; } 41 | 42 | public string ContentsRegex { get; set; } 43 | 44 | public string FileNameDenyRegex { get; set; } 45 | 46 | public string FileNameAllowRegex { get; set; } 47 | 48 | /// 49 | /// Gets or sets a value indicating the length of a typical match. 50 | /// If this value is non-zero, the scanner will first attempt 51 | /// to detect a base64-encoded value that decodes to this length. 52 | /// On detection, it will next decode this value and provide the 53 | /// decoded string to the match expression. No base64-decoding 54 | /// occurs when this property is 0 or less. 55 | /// 56 | public Base64EncodingMatch Base64EncodingMatch { get; set; } 57 | 58 | public Dictionary Properties { get; set; } 59 | 60 | public Dictionary MessageArguments { get; set; } 61 | 62 | public IList Notes { get; set; } 63 | 64 | public IDictionary Fixes { get; set; } 65 | 66 | public Dictionary ArgumentNameToIndexMap { get; set; } 67 | 68 | public bool IsValidatorEnabled { get; set; } = true; 69 | 70 | public string MessageId { get; set; } = "Default"; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/Test.UnitTests.Strings.Interop/FlexStringTests.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Xunit; 5 | 6 | namespace Microsoft.Strings.Interop 7 | { 8 | public class FlexStringTests 9 | { 10 | [Fact] 11 | public void FlexString_Basics() 12 | { 13 | string sample; 14 | String8 sample8; 15 | FlexString sampleF, sampleF2; 16 | 17 | // Null handling 18 | Assert.True(FlexString.IsNullOrEmpty((FlexString)null)); 19 | Assert.True(FlexString.IsNullOrEmpty((string)null)); 20 | Assert.True(FlexString.IsNullOrEmpty("")); 21 | Assert.True(FlexString.IsNullOrEmpty(String8.Empty)); 22 | 23 | Assert.True(FlexString.IsNull((FlexString)null)); 24 | Assert.True(FlexString.IsNull((string)null)); 25 | 26 | sample = null; 27 | sampleF = sample; 28 | sample8 = sampleF; 29 | Assert.True(FlexString.IsNullOrEmpty(sampleF)); 30 | 31 | //Null check with null strings 32 | Assert.True(FlexString.IsNull(sample)); 33 | Assert.True(FlexString.IsNull(sampleF)); 34 | Assert.False(FlexString.IsNull(sample8)); 35 | 36 | // Implicit conversions 37 | sample = "sample"; 38 | sampleF = sample; 39 | sample8 = sampleF; 40 | Assert.Equal("sample", sample8.ToString()); 41 | 42 | //Null check with populated strings 43 | Assert.False(FlexString.IsNull(sample)); 44 | Assert.False(FlexString.IsNull(sampleF)); 45 | Assert.False(FlexString.IsNull(sample8)); 46 | 47 | sample8 = String8.ConvertExpensively("sample2"); 48 | sampleF = sample8; 49 | sample = sampleF; 50 | Assert.Equal("sample2", sample); 51 | 52 | // CompareTo 53 | Assert.Equal(0, sampleF.CompareTo(sample)); 54 | Assert.Equal(0, sampleF.CompareTo(sample8)); 55 | Assert.Equal(0, sampleF.CompareTo(sampleF)); 56 | sampleF = "sample3"; 57 | Assert.NotEqual(0, sampleF.CompareTo(sample)); 58 | Assert.NotEqual(0, sampleF.CompareTo(sample8)); 59 | sampleF2 = "sample3"; 60 | Assert.Equal(0, sampleF.CompareTo(sampleF2)); 61 | sampleF2 = "different"; 62 | Assert.NotEqual(0, sampleF.CompareTo(sampleF2)); 63 | } 64 | } 65 | } 66 | --------------------------------------------------------------------------------