diff --git a/src/SLCore.Listeners.UnitTests/Implementation/TaintVulnerabilityListenerTests.cs b/src/SLCore.Listeners.UnitTests/Implementation/TaintVulnerabilityListenerTests.cs new file mode 100644 index 0000000000..4b00ae86ef --- /dev/null +++ b/src/SLCore.Listeners.UnitTests/Implementation/TaintVulnerabilityListenerTests.cs @@ -0,0 +1,34 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using SonarLint.VisualStudio.SLCore.Core; +using SonarLint.VisualStudio.SLCore.Listener.Taint; + +namespace SonarLint.VisualStudio.SLCore.Listeners.UnitTests.Implementation; + +[TestClass] +public class TaintVulnerabilityListenerTests +{ + [TestMethod] + public void MefCtor_CheckIsExported() => MefTestHelpers.CheckTypeCanBeImported(); + + [TestMethod] + public void MefCtor_CheckIsSingleton() => MefTestHelpers.CheckIsSingletonMefComponent(); +} diff --git a/src/SLCore.Listeners/Implementation/TaintVulnerabilityListener.cs b/src/SLCore.Listeners/Implementation/TaintVulnerabilityListener.cs new file mode 100644 index 0000000000..f983ae055f --- /dev/null +++ b/src/SLCore.Listeners/Implementation/TaintVulnerabilityListener.cs @@ -0,0 +1,43 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using System.ComponentModel.Composition; +using Newtonsoft.Json; +using SonarLint.VisualStudio.Core; +using SonarLint.VisualStudio.SLCore.Core; +using SonarLint.VisualStudio.SLCore.Listener.Taint; + +namespace SonarLint.VisualStudio.SLCore.Listeners.Implementation; + +[Export(typeof(ISLCoreListener))] +[PartCreationPolicy(CreationPolicy.Shared)] +public class TaintVulnerabilityListener : ITaintVulnerabilityListener +{ + + [ImportingConstructor] + public TaintVulnerabilityListener() + { + } + + public void DidChangeTaintVulnerabilities(DidChangeTaintVulnerabilitiesParams parameters) + { + // todo https://sonarsource.atlassian.net/browse/SLVS-1592 + } +} diff --git a/src/SLCore.UnitTests/Common/Models/TaintVulnerabilityDtoTests.cs b/src/SLCore.UnitTests/Common/Models/TaintVulnerabilityDtoTests.cs new file mode 100644 index 0000000000..e9c3a662c7 --- /dev/null +++ b/src/SLCore.UnitTests/Common/Models/TaintVulnerabilityDtoTests.cs @@ -0,0 +1,119 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using Newtonsoft.Json; +using SonarLint.VisualStudio.SLCore.Common.Models; +using SonarLint.VisualStudio.SLCore.Service.Rules.Models; + +namespace SonarLint.VisualStudio.SLCore.UnitTests.Common.Models; + +[TestClass] +public class TaintVulnerabilityDtoTests +{ + [TestMethod] + public void Deserialized_AsExpected() + { + var expected = new TaintVulnerabilityDto( + Guid.Parse("f1276bb9-54a4-4cbd-b4ac-41d2541302ee"), + "AXgSTUZl007Zyo8hMhT-", + false, + "roslyn.sonaranalyzer.security.cs:S5135", + "Change this code to not deserialize user-controlled data.", + "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Taint\\XmlSerializerInjectionController.cs", + DateTimeOffset.FromUnixTimeMilliseconds(1615214736000), + new MQRModeDetails(CleanCodeAttribute.COMPLETE, [new ImpactDto(SoftwareQuality.SECURITY, ImpactSeverity.HIGH)]), + [ + new TaintFlowDto([ + new TaintLocationDto(new TextRangeWithHashDto(20, 32, 20, 58, "f677236678ac4b2ab451d66d4b251e8f"), + "Sink: this invocation is not safe; a malicious value can be injected into the caller", + "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Taint\\XmlSerializerInjectionController.cs") + ]) + ], + new TextRangeWithHashDto(20, 32, 20, 58, "f677236678ac4b2ab451d66d4b251e8f"), + null, + false); + + const string serialized = + """ + { + "id": "f1276bb9-54a4-4cbd-b4ac-41d2541302ee", + "sonarServerKey": "AXgSTUZl007Zyo8hMhT-", + "resolved": false, + "ruleKey": "roslyn.sonaranalyzer.security.cs:S5135", + "message": "Change this code to not deserialize user-controlled data.", + "ideFilePath": "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Taint\\XmlSerializerInjectionController.cs", + "introductionDate": 1615214736000, + "severityMode": { + "cleanCodeAttribute": "COMPLETE", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ] + }, + "severity": "BLOCKER", + "type": "VULNERABILITY", + "flows": [ + { + "locations": [ + { + "textRange": { + "startLine": 20, + "startLineOffset": 32, + "endLine": 20, + "endLineOffset": 58, + "hash": "f677236678ac4b2ab451d66d4b251e8f" + }, + "message": "Sink: this invocation is not safe; a malicious value can be injected into the caller", + "filePath": "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Taint\\XmlSerializerInjectionController.cs" + } + ] + } + ], + "textRange": { + "startLine": 20, + "startLineOffset": 32, + "endLine": 20, + "endLineOffset": 58, + "hash": "f677236678ac4b2ab451d66d4b251e8f" + }, + "ruleDescriptionContextKey": null, + "cleanCodeAttribute": "COMPLETE", + "impacts": { + "SECURITY": "HIGH" + }, + "isOnNewCode": false + } + """; + + var actual = JsonConvert.DeserializeObject(serialized); + + actual + .Should() + .BeEquivalentTo(expected, + options => + options + .ComparingByMembers() + .ComparingByMembers() + .ComparingByMembers() + .ComparingByMembers()); + } +} diff --git a/src/SLCore.UnitTests/Listener/Taint/DidChangeTaintVulnerabilitiesParamsTests.cs b/src/SLCore.UnitTests/Listener/Taint/DidChangeTaintVulnerabilitiesParamsTests.cs new file mode 100644 index 0000000000..8c3636e282 --- /dev/null +++ b/src/SLCore.UnitTests/Listener/Taint/DidChangeTaintVulnerabilitiesParamsTests.cs @@ -0,0 +1,177 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using Newtonsoft.Json; +using SonarLint.VisualStudio.SLCore.Listener.Taint; + +namespace SonarLint.VisualStudio.SLCore.UnitTests.Listener.Taint; + +[TestClass] +public class DidChangeTaintVulnerabilitiesParamsTests +{ + [TestMethod] + public void Deserialized_AsExpected_SmokeTest() + { + const string serialized = + """ + { + "configurationScopeId": "SLVS_Bound_VS2019", + "closedTaintVulnerabilityIds": [ "62294585-d219-4d07-8e40-6d28d2f2f90e", "62294585-d219-4d07-8e40-6d28d2f2f90e", "62294585-d219-4d07-8e40-6d28d2f2f90e" ], + "addedTaintVulnerabilities": [ + { + "id": "62294585-d219-4d07-8e40-6d28d2f2f90e", + "sonarServerKey": "AXgSTUbU007Zyo8hMhUK", + "resolved": false, + "ruleKey": "roslyn.sonaranalyzer.security.cs:S2091", + "message": "Change this code to not construct this XPath expression from user-controlled data.", + "ideFilePath": "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Taint\\XPathInjectionController.cs", + "introductionDate": 1615214736000, + "severityMode": { + "cleanCodeAttribute": "COMPLETE", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ] + }, + "severity": "BLOCKER", + "type": "VULNERABILITY", + "flows": [ + { + "locations": [] + }, + { + "locations": [] + } + ], + "textRange": { + "startLine": 23, + "startLineOffset": 27, + "endLine": 23, + "endLineOffset": 59, + "hash": "4fdeebd4a19fd4b1c4c5b9b43ea9f71e" + }, + "ruleDescriptionContextKey": null, + "cleanCodeAttribute": "COMPLETE", + "impacts": { + "SECURITY": "HIGH" + }, + "isOnNewCode": false + }, + { + "id": "62294585-d219-4d07-8e40-6d28d2f2f90e", + "sonarServerKey": "AXgSTUbU007Zyo8hMhUK", + "resolved": false, + "ruleKey": "roslyn.sonaranalyzer.security.cs:S2091", + "message": "Change this code to not construct this XPath expression from user-controlled data.", + "ideFilePath": "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Taint\\XPathInjectionController.cs", + "introductionDate": 1615214736000, + "severityMode": { + "cleanCodeAttribute": "COMPLETE", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ] + }, + "severity": "BLOCKER", + "type": "VULNERABILITY", + "flows": [ + { + "locations": [] + }, + { + "locations": [] + } + ], + "textRange": { + "startLine": 23, + "startLineOffset": 27, + "endLine": 23, + "endLineOffset": 59, + "hash": "4fdeebd4a19fd4b1c4c5b9b43ea9f71e" + }, + "ruleDescriptionContextKey": null, + "cleanCodeAttribute": "COMPLETE", + "impacts": { + "SECURITY": "HIGH" + }, + "isOnNewCode": false + } + ], + "updatedTaintVulnerabilities": [ + { + "id": "62294585-d219-4d07-8e40-6d28d2f2f90e", + "sonarServerKey": "AXgSTUbU007Zyo8hMhUK", + "resolved": false, + "ruleKey": "roslyn.sonaranalyzer.security.cs:S2091", + "message": "Change this code to not construct this XPath expression from user-controlled data.", + "ideFilePath": "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Taint\\XPathInjectionController.cs", + "introductionDate": 1615214736000, + "severityMode": { + "cleanCodeAttribute": "COMPLETE", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ] + }, + "severity": "BLOCKER", + "type": "VULNERABILITY", + "flows": [ + { + "locations": [] + }, + { + "locations": [] + } + ], + "textRange": { + "startLine": 23, + "startLineOffset": 27, + "endLine": 23, + "endLineOffset": 59, + "hash": "4fdeebd4a19fd4b1c4c5b9b43ea9f71e" + }, + "ruleDescriptionContextKey": null, + "cleanCodeAttribute": "COMPLETE", + "impacts": { + "SECURITY": "HIGH" + }, + "isOnNewCode": false + } + ] + } + """; + + var actual = JsonConvert.DeserializeObject(serialized); + + actual.configurationScopeId.Should().Be("SLVS_Bound_VS2019"); + actual.closedTaintVulnerabilityIds.Should().HaveCount(3); + actual.closedTaintVulnerabilityIds.Should().NotContain(Guid.Empty); + actual.addedTaintVulnerabilities.Should().HaveCount(2); + actual.addedTaintVulnerabilities.Should().NotContainNulls(); + actual.updatedTaintVulnerabilities.Should().HaveCount(1); + actual.updatedTaintVulnerabilities.Should().NotContainNulls(); + } +} diff --git a/src/SLCore.UnitTests/Service/Taint/ListAllTaintsParamsTests.cs b/src/SLCore.UnitTests/Service/Taint/ListAllTaintsParamsTests.cs new file mode 100644 index 0000000000..b8570547df --- /dev/null +++ b/src/SLCore.UnitTests/Service/Taint/ListAllTaintsParamsTests.cs @@ -0,0 +1,40 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using Newtonsoft.Json; +using SonarLint.VisualStudio.SLCore.Service.Taint; + +namespace SonarLint.VisualStudio.SLCore.UnitTests.Service.Taint; + +[TestClass] +public class ListAllTaintsParamsTests +{ + [DataTestMethod] + [DataRow("scope 1", false)] + [DataRow("other scope 2", true)] + public void Serialized_AsExpected(string configurationScopeId, bool shouldRefresh) + { + var expected = $$"""{"configurationScopeId":"{{configurationScopeId}}","shouldRefresh":{{shouldRefresh.ToString().ToLower()}}}"""; + + var listAllTaintsParams = new ListAllTaintsParams(configurationScopeId, shouldRefresh); + + JsonConvert.SerializeObject(listAllTaintsParams).Should().Be(expected); + } +} diff --git a/src/SLCore.UnitTests/Service/Taint/ListAllTaintsResponseTests.cs b/src/SLCore.UnitTests/Service/Taint/ListAllTaintsResponseTests.cs new file mode 100644 index 0000000000..192d48bcb6 --- /dev/null +++ b/src/SLCore.UnitTests/Service/Taint/ListAllTaintsResponseTests.cs @@ -0,0 +1,360 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using Newtonsoft.Json; +using SonarLint.VisualStudio.SLCore.Service.Taint; + +namespace SonarLint.VisualStudio.SLCore.UnitTests.Service.Taint; + +[TestClass] +public class ListAllTaintsResponseTests +{ + [TestMethod] + public void Deserialized_AsExpected_SmokeTest() + { + const string serialized = """ + { + "taintVulnerabilities": [ + { + "id": "f1276bb9-54a4-4cbd-b4ac-41d2541302ee", + "sonarServerKey": "AXgSTUZl007Zyo8hMhT-", + "resolved": false, + "ruleKey": "roslyn.sonaranalyzer.security.cs:S5135", + "message": "Change this code to not deserialize user-controlled data.", + "ideFilePath": "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Taint\\XmlSerializerInjectionController.cs", + "introductionDate": 1615214736000, + "severityMode": { + "cleanCodeAttribute": "COMPLETE", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ] + }, + "severity": "BLOCKER", + "type": "VULNERABILITY", + "flows": [ + { + "locations": [] + } + ], + "textRange": { + "startLine": 20, + "startLineOffset": 32, + "endLine": 20, + "endLineOffset": 58, + "hash": "f677236678ac4b2ab451d66d4b251e8f" + }, + "ruleDescriptionContextKey": null, + "cleanCodeAttribute": "COMPLETE", + "impacts": { + "SECURITY": "HIGH" + }, + "isOnNewCode": false + }, + { + "id": "95c062cf-b30f-4cc4-88db-f9fee7344639", + "sonarServerKey": "AXgSTUbP007Zyo8hMhUG", + "resolved": false, + "ruleKey": "roslyn.sonaranalyzer.security.cs:S2083", + "message": "Change this code to not construct the path from user-controlled data.", + "ideFilePath": "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Taint\\MixedIssuesController.cs", + "introductionDate": 1615214736000, + "severityMode": { + "cleanCodeAttribute": "COMPLETE", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ] + }, + "severity": "BLOCKER", + "type": "VULNERABILITY", + "flows": [ + { + "locations": [] + } + ], + "textRange": { + "startLine": 15, + "startLineOffset": 12, + "endLine": 15, + "endLineOffset": 43, + "hash": "75a2a40f1881db4654f6860a1114a0bf" + }, + "ruleDescriptionContextKey": null, + "cleanCodeAttribute": "COMPLETE", + "impacts": { + "SECURITY": "HIGH" + }, + "isOnNewCode": false + }, + { + "id": "a7ef1f6e-523b-49f5-a29a-9b549695b0e0", + "sonarServerKey": "AXgSTUbP007Zyo8hMhUH", + "resolved": true, + "ruleKey": "roslyn.sonaranalyzer.security.cs:S5135", + "message": "Change this code to not deserialize user-controlled data.", + "ideFilePath": "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Taint\\MixedIssuesController.cs", + "introductionDate": 1615214736000, + "severityMode": { + "cleanCodeAttribute": "COMPLETE", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ] + }, + "severity": "BLOCKER", + "type": "VULNERABILITY", + "flows": [ + { + "locations": [] + } + ], + "textRange": { + "startLine": 34, + "startLineOffset": 32, + "endLine": 34, + "endLineOffset": 58, + "hash": "f677236678ac4b2ab451d66d4b251e8f" + }, + "ruleDescriptionContextKey": null, + "cleanCodeAttribute": "COMPLETE", + "impacts": { + "SECURITY": "HIGH" + }, + "isOnNewCode": false + }, + { + "id": "a7cbd2da-71e4-4a93-80fb-f0cd6ca9da89", + "sonarServerKey": "AXgSTUbP007Zyo8hMhUF", + "resolved": false, + "ruleKey": "roslyn.sonaranalyzer.security.cs:S2091", + "message": "Change this code to not construct this XPath expression from user-controlled data.", + "ideFilePath": "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Taint\\MixedIssuesController.cs", + "introductionDate": 1615214736000, + "severityMode": { + "cleanCodeAttribute": "COMPLETE", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ] + }, + "severity": "BLOCKER", + "type": "VULNERABILITY", + "flows": [ + { + "locations": [] + }, + { + "locations": [] + } + ], + "textRange": { + "startLine": 58, + "startLineOffset": 27, + "endLine": 58, + "endLineOffset": 59, + "hash": "4fdeebd4a19fd4b1c4c5b9b43ea9f71e" + }, + "ruleDescriptionContextKey": null, + "cleanCodeAttribute": "COMPLETE", + "impacts": { + "SECURITY": "HIGH" + }, + "isOnNewCode": false + }, + { + "id": "352ea2a3-e77f-49a8-880b-9549504be448", + "sonarServerKey": "AYfh2w3VueSGJHh8vWDj", + "resolved": false, + "ruleKey": "roslyn.sonaranalyzer.security.cs:S5146", + "message": "Change this code to not perform redirects based on user-controlled data.", + "ideFilePath": "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Controllers\\WeatherForecastController.cs", + "introductionDate": 1681210777000, + "severityMode": { + "cleanCodeAttribute": "COMPLETE", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ] + }, + "severity": "BLOCKER", + "type": "VULNERABILITY", + "flows": [ + { + "locations": [] + } + ], + "textRange": { + "startLine": 43, + "startLineOffset": 12, + "endLine": 43, + "endLineOffset": 34, + "hash": "9e3e6f8af5838423c1b97b7d423cebab" + }, + "ruleDescriptionContextKey": null, + "cleanCodeAttribute": "COMPLETE", + "impacts": { + "SECURITY": "HIGH" + }, + "isOnNewCode": true + }, + { + "id": "abca89aa-c7a7-44c1-92e6-41b7a639e51c", + "sonarServerKey": "AXgSV_UkF9imBvjh6CmG", + "resolved": false, + "ruleKey": "roslyn.sonaranalyzer.security.cs:S2083", + "message": "Change this code to not construct the path from user-controlled data.", + "ideFilePath": "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Taint\\MultiFlow_IOPathInjectionController.cs", + "introductionDate": 1615215436000, + "severityMode": { + "cleanCodeAttribute": "COMPLETE", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ] + }, + "severity": "BLOCKER", + "type": "VULNERABILITY", + "flows": [ + { + "locations": [] + } + ], + "textRange": { + "startLine": 17, + "startLineOffset": 12, + "endLine": 17, + "endLineOffset": 43, + "hash": "75a2a40f1881db4654f6860a1114a0bf" + }, + "ruleDescriptionContextKey": null, + "cleanCodeAttribute": "COMPLETE", + "impacts": { + "SECURITY": "HIGH" + }, + "isOnNewCode": false + }, + { + "id": "2f91bf04-f867-413c-8453-8f36d9756001", + "sonarServerKey": "AXgSV_UkF9imBvjh6CmF", + "resolved": false, + "ruleKey": "roslyn.sonaranalyzer.security.cs:S2083", + "message": "Change this code to not construct the path from user-controlled data.", + "ideFilePath": "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Taint\\MultiFlow_IOPathInjectionController.cs", + "introductionDate": 1615215436000, + "severityMode": { + "cleanCodeAttribute": "COMPLETE", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ] + }, + "severity": "BLOCKER", + "type": "VULNERABILITY", + "flows": [ + { + "locations": [] + }, + { + "locations": [] + }, + { + "locations": [] + } + ], + "textRange": { + "startLine": 53, + "startLineOffset": 12, + "endLine": 53, + "endLineOffset": 43, + "hash": "75a2a40f1881db4654f6860a1114a0bf" + }, + "ruleDescriptionContextKey": null, + "cleanCodeAttribute": "COMPLETE", + "impacts": { + "SECURITY": "HIGH" + }, + "isOnNewCode": false + }, + { + "id": "62294585-d219-4d07-8e40-6d28d2f2f90e", + "sonarServerKey": "AXgSTUbU007Zyo8hMhUK", + "resolved": false, + "ruleKey": "roslyn.sonaranalyzer.security.cs:S2091", + "message": "Change this code to not construct this XPath expression from user-controlled data.", + "ideFilePath": "sonarlint-visualstudio-sampleprojects\\bound\\sonarcloud\\SLVS_Samples_Bound_VS2019\\Taint_CSharp_NetCore_WebAppReact\\Taint\\XPathInjectionController.cs", + "introductionDate": 1615214736000, + "severityMode": { + "cleanCodeAttribute": "COMPLETE", + "impacts": [ + { + "softwareQuality": "SECURITY", + "impactSeverity": "HIGH" + } + ] + }, + "severity": "BLOCKER", + "type": "VULNERABILITY", + "flows": [ + { + "locations": [] + }, + { + "locations": [] + } + ], + "textRange": { + "startLine": 23, + "startLineOffset": 27, + "endLine": 23, + "endLineOffset": 59, + "hash": "4fdeebd4a19fd4b1c4c5b9b43ea9f71e" + }, + "ruleDescriptionContextKey": null, + "cleanCodeAttribute": "COMPLETE", + "impacts": { + "SECURITY": "HIGH" + }, + "isOnNewCode": false + } + ] + } + """; + + var actual = JsonConvert.DeserializeObject(serialized); + + actual.taintVulnerabilities.Count.Should().Be(8); + actual.taintVulnerabilities.Should().NotContainNulls(); + } +} diff --git a/src/SLCore/Common/Models/TaintVulnerabilityDto.cs b/src/SLCore/Common/Models/TaintVulnerabilityDto.cs new file mode 100644 index 0000000000..fb3ba41e52 --- /dev/null +++ b/src/SLCore/Common/Models/TaintVulnerabilityDto.cs @@ -0,0 +1,44 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using Newtonsoft.Json; +using SonarLint.VisualStudio.SLCore.Common.Helpers; +using SonarLint.VisualStudio.SLCore.Protocol; +using SonarLint.VisualStudio.SLCore.Service.Rules.Models; + +namespace SonarLint.VisualStudio.SLCore.Common.Models; + +public record TaintVulnerabilityDto( + Guid id, + string sonarServerKey, + bool resolved, + string ruleKey, + string message, + string ideFilePath, + [JsonConverter(typeof(MillisecondUnixTimestampDateTimeOffsetConverter))]DateTimeOffset introductionDate, + [JsonConverter(typeof(EitherJsonConverter))]Either severityMode, + List flows, + TextRangeWithHashDto textRange, + string ruleDescriptionContextKey, + bool isOnNewCode); + +public record TaintFlowDto(List locations); + +public record TaintLocationDto(TextRangeWithHashDto textRange, string message, string filePath); diff --git a/src/SLCore/Common/Models/TextRangeWithHashDto.cs b/src/SLCore/Common/Models/TextRangeWithHashDto.cs new file mode 100644 index 0000000000..f45eb9b443 --- /dev/null +++ b/src/SLCore/Common/Models/TextRangeWithHashDto.cs @@ -0,0 +1,23 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +namespace SonarLint.VisualStudio.SLCore.Common.Models; + +public record TextRangeWithHashDto(int startLine, int startLineOffset, int endLine, int endLineOffset, string hash); diff --git a/src/SLCore/Listener/Taint/DidChangeTaintVulnerabilitiesParams.cs b/src/SLCore/Listener/Taint/DidChangeTaintVulnerabilitiesParams.cs new file mode 100644 index 0000000000..65ff7d11fc --- /dev/null +++ b/src/SLCore/Listener/Taint/DidChangeTaintVulnerabilitiesParams.cs @@ -0,0 +1,29 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using SonarLint.VisualStudio.SLCore.Common.Models; + +namespace SonarLint.VisualStudio.SLCore.Listener.Taint; + +public record DidChangeTaintVulnerabilitiesParams( + string configurationScopeId, + List closedTaintVulnerabilityIds, + List addedTaintVulnerabilities, + List updatedTaintVulnerabilities); diff --git a/src/SLCore/Listener/Taint/ITaintVulnerabilityListener.cs b/src/SLCore/Listener/Taint/ITaintVulnerabilityListener.cs new file mode 100644 index 0000000000..a8fe71d32e --- /dev/null +++ b/src/SLCore/Listener/Taint/ITaintVulnerabilityListener.cs @@ -0,0 +1,28 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using SonarLint.VisualStudio.SLCore.Core; + +namespace SonarLint.VisualStudio.SLCore.Listener.Taint; + +public interface ITaintVulnerabilityListener : ISLCoreListener +{ + void DidChangeTaintVulnerabilities(DidChangeTaintVulnerabilitiesParams parameters); +} diff --git a/src/SLCore/Service/Taint/ListAllTaintsParams.cs b/src/SLCore/Service/Taint/ListAllTaintsParams.cs new file mode 100644 index 0000000000..940d808a56 --- /dev/null +++ b/src/SLCore/Service/Taint/ListAllTaintsParams.cs @@ -0,0 +1,23 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +namespace SonarLint.VisualStudio.SLCore.Service.Taint; + +public record ListAllTaintsParams(string configurationScopeId, bool shouldRefresh); diff --git a/src/SLCore/Service/Taint/ListAllTaintsResponse.cs b/src/SLCore/Service/Taint/ListAllTaintsResponse.cs new file mode 100644 index 0000000000..c52aacba4b --- /dev/null +++ b/src/SLCore/Service/Taint/ListAllTaintsResponse.cs @@ -0,0 +1,25 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using SonarLint.VisualStudio.SLCore.Common.Models; + +namespace SonarLint.VisualStudio.SLCore.Service.Taint; + +public record ListAllTaintsResponse(List taintVulnerabilities); diff --git a/src/SLCore/Service/Taint/TaintVulnerabilityTrackingSLCoreService.cs b/src/SLCore/Service/Taint/TaintVulnerabilityTrackingSLCoreService.cs new file mode 100644 index 0000000000..2e377c0882 --- /dev/null +++ b/src/SLCore/Service/Taint/TaintVulnerabilityTrackingSLCoreService.cs @@ -0,0 +1,30 @@ +/* + * SonarLint for Visual Studio + * Copyright (C) 2016-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +using SonarLint.VisualStudio.SLCore.Core; +using SonarLint.VisualStudio.SLCore.Protocol; + +namespace SonarLint.VisualStudio.SLCore.Service.Taint; + +[JsonRpcClass("taintVulnerability")] +public interface ITaintVulnerabilityTrackingSlCoreService : ISLCoreService +{ + Task ListAllAsync(ListAllTaintsParams parameters); +}