CVE-2022-24441 (C#, published 2022-11-30T13:15Z)
Description: value: The package snyk before 1.1064.0 are vulnerable to Code Injection when analyzing a project. An attacker who can convince a user to scan a malicious project can include commands in a build file such as build.gradle or gradle-wrapper.jar, which will be executed with the privileges of the application. This vulnerability may be triggered when running the the CLI tool directly, or when running a scan with one of the IDE plugins that invoke the Snyk CLI. Successful exploitation of this issue would likely require some level of social engineering - to coerce an untrusted project to be downloaded and analyzed via the Snyk CLI or opened in an IDE where a Snyk IDE plugin is installed and enabled. Additionally, if the IDE has a Trust feature then the target folder must be marked as ‘trusted’ in order to be vulnerable. **NOTE:** This issue is independent of the one reported in [CVE-2022-40764](https://security.snyk.io/vuln/SNYK-JS-SNYK-3037342), and upgrading to a fixed version for this addresses that issue as well. The affected IDE plugins and versions are: - VS Code - Affected: <=1.8.0, Fixed: 1.9.0 - IntelliJ - Affected: <=2.4.47, Fixed: 2.4.48 - Visual Studio - Affected: <=1.1.30, Fixed: 1.1.31 - Eclipse - Affected: <=v20221115.132308, Fixed: All subsequent versions - Language Server - Affected: <=v20221109.114426, Fixed: All subsequent versions
Severity: nan (CVSS v3 base score: 8.8)
Weakness: CWE-78 \u2014 Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
The product constructs all or part of an OS command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended OS command when it is sent to a downstream component.
Repository: https://github.com/snyk/snyk-visual-studio-plugin
Files changed:
CHANGELOG.md
Snyk.VisualStudio.Extension.2022/Snyk.VisualStudio.Extension.2022.csproj
Snyk.VisualStudio.Extension.2022/TrustDialogWindow.xaml
Snyk.VisualStudio.Extension.2022/TrustDialogWindow.xaml.cs
Snyk.VisualStudio.Extension.Shared/Service/ISnykServiceProvider.cs
Snyk.VisualStudio.Extension.Shared/Service/IWorkspaceTrustService.cs
Snyk.VisualStudio.Extension.Shared/Service/SnykService.cs
Snyk.VisualStudio.Extension.Shared/Service/SnykTasksService.cs
Snyk.VisualStudio.Extension.Shared/Service/WorkspaceTrustService.cs
Snyk.VisualStudio.Extension.Shared/Settings/IUserStorageSettingsService.cs
Snyk.VisualStudio.Extension.Shared/Settings/SnykSettings.cs
Snyk.VisualStudio.Extension.Shared/Settings/SnykUserStorageSettingsService.cs
Snyk.VisualStudio.Extension.Shared/Snyk.VisualStudio.Extension.Shared.projitems
Snyk.VisualStudio.Extension.Shared/UI/Toolwindow/MessagePanel.xaml
Snyk.VisualStudio.Extension.Shared/UI/Toolwindow/MessagePanel.xaml.cs
Snyk.VisualStudio.Extension.Tests/Service/WorkspaceTrustServiceTest.cs
Snyk.VisualStudio.Extension/Snyk.VisualStudio.Extension.csproj
Snyk.VisualStudio.Extension/TrustDialogWindow.xaml
Snyk.VisualStudio.Extension/TrustDialogWindow.xaml.cs
Commit message: feat: add workspace trust (#217)



Vulnerable code:
 

        /// Gets or sets the value of the custom CLI path
    public class SnykUserStorageSettingsService
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:c="clr-namespace:Snyk.VisualStudio.Extension.Shared.UI.Controls" 
             mc:Ignorable="d" 
        
        
                    2. Analyze code for issues and vulnerabilities                
                        Test code now
                <TextBlock FontSize="11">                    
	<DeployVsixExtensionFilesDependsOn>$(DeployVsixExtensionFilesDependsOn);SaveSettingsJsonFile</DeployVsixExtensionFilesDependsOn>
  <ItemGroup />
      <ItemGroup>
          <VSIXSourceItem Include="@(ReferencePath)" />
      </ItemGroup>
  <Target Name="SaveSettingsJsonFile"
          DependsOnTargets="GetVsixDeploymentPath">
	<Message Condition="!Exists('$(VsixDeploymentPath)settings.json')"
	  Importance="High" 
      Text="settings.json does not exist, skipping step"/>
    <Message Condition="Exists('$(VsixDeploymentPath)settings.json')"
      Importance="High" 
      Text="Saving settings.json file from $(VsixDeploymentPath)settings.json"/>
    <Move Condition="Exists('$(VsixDeploymentPath)settings.json')"
          SourceFiles="$(VsixDeploymentPath)settings.json"
          DestinationFiles="$(IntermediateOutputPath)settings.json"/>
  <Target Name="AfterBuild" 
          DependsOnTargets="GetVsixDeploymentPath">
    <Message 
      Condition="Exists('$(IntermediateOutputPath)settings.json')"
      Text="Copying settings.json back to $(VsixDeploymentPath)" 
      Importance="High"/>
    <Move Condition="Exists('$(IntermediateOutputPath)settings.json')"
          DestinationFiles="$(VsixDeploymentPath)settings.json"
          SourceFiles="$(IntermediateOutputPath)settings.json"/>

Fixed code:
## [1.1.31]

### Added
- Adds workspace trust mechanism to ensure scans are run on the trusted projects.


    <Compile Include="TrustDialogWindow.xaml.cs">
      <DependentUpon>TrustDialogWindow.xaml</DependentUpon>
    </Compile>
  <ItemGroup>
    <Page Include="TrustDialogWindow.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
  </ItemGroup>
﻿<ui:DialogWindow x:Class="Snyk.VisualStudio.Extension.TrustDialogWindow"
                 x:Name="TrustWindow"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:toolkit="clr-namespace:Community.VisualStudio.Toolkit;assembly=Community.VisualStudio.Toolkit"
                 xmlns:ui="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.15.0"
                 mc:Ignorable="d"
                 WindowStartupLocation="CenterScreen"
                 IsCloseButtonEnabled="True"
                 HasHelpButton="False"
                 MinHeight="290" Height="290"
                 MinWidth="500" Width="500"
                 BorderBrush="{x:Static SystemColors.WindowFrameBrush}" BorderThickness="1"
                 WindowStyle="None" ResizeMode="NoResize" AllowsTransparency="True"
                 xmlns:catalog="clr-namespace:Microsoft.VisualStudio.Imaging;assembly=Microsoft.VisualStudio.ImageCatalog"
                 xmlns:imaging="clr-namespace:Microsoft.VisualStudio.Imaging;assembly=Microsoft.VisualStudio.Imaging"
                 toolkit:Themes.UseVsTheme="True"
                 Title="Snyk - This folder has not been trusted"
                 MouseDown="TrustDialogWindow_OnMouseDown">
    <DockPanel Margin="10">
        <Button DockPanel.Dock="Top" HorizontalAlignment="Right" Click="DoNotTrustButton_OnClick" MinWidth="1" MinHeight="1" Width="35" Margin="0" Padding="0">
            <imaging:CrispImage Moniker="{x:Static catalog:KnownMonikers.Close}"/>
        </Button>
        <StackPanel HorizontalAlignment="Right" DockPanel.Dock="Bottom" Orientation="Horizontal">
            <Button x:Name="TrustButton" Margin="5, 5" Content="Trust folder and continue" Click="TrustButton_OnClick"/>
            <Button x:Name="DoNotTrustButton" Margin="5, 5" Content="Don't scan" Click="DoNotTrustButton_OnClick"/>
        </StackPanel>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
            </Grid.RowDefinitions>
            <Grid Grid.Row="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="5*"/>
                </Grid.ColumnDefinitions>
                    <imaging:CrispImage Grid.Column="0" Width="50" Moniker="{x:Static catalog:KnownMonikers.StatusSecurityWarning}"/>
                <StackPanel VerticalAlignment="Center" Grid.Column="1" Margin="0, 0, 5, 0">
                    <TextBlock FontSize="14">This folder has not been trusted:</TextBlock>
                    <TextBlock FontSize="14" FontWeight="Bold" TextWrapping="Wrap" Text="{Binding ElementName=TrustWindow, Path=FolderPath}"/>
                </StackPanel>
            </Grid>
            <StackPanel Grid.Row="1" Margin="5">
                <TextBlock TextWrapping="Wrap">
                    When scanning folder files for vulnerabilities, Snyk may automatically execute code such as invoking the package manager to get dependency information. You should only scan folders you trust.
                </TextBlock>
                <TextBlock>
                    <LineBreak/>
                    <Hyperlink NavigateUri="https://docs.snyk.io/ide-tools/visual-studio-extension/workspace-trust" RequestNavigate="Hyperlink_OnRequestNavigate">
                        More information
                    </Hyperlink>
                </TextBlock>
            </StackPanel>
        </Grid>
    </DockPanel>
</ui:DialogWindow>
﻿
namespace Snyk.VisualStudio.Extension
{
    using System.Diagnostics;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Navigation;
    using Microsoft.VisualStudio.PlatformUI;

    /// <summary>
    /// Trusted dialog window for Visual Studio 2022.
    /// </summary>
    public partial class TrustDialogWindow : DialogWindow
    {
        public TrustDialogWindow(string folderPath)
        {
            this.FolderPath = folderPath;
            this.InitializeComponent();
        }

        public string FolderPath { get; }

        private void DoNotTrustButton_OnClick(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
            this.Close();
        }

        private void TrustButton_OnClick(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
            this.Close();
        }

        private void Hyperlink_OnRequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
            e.Handled = true;
        }

        private void TrustDialogWindow_OnMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ChangedButton == MouseButton.Left)
            {
                this.DragMove();
            }
        }
    }
}
        IWorkspaceTrustService WorkspaceTrustService { get; }

﻿namespace Snyk.VisualStudio.Extension.Shared.Service
{
    public interface IWorkspaceTrustService
    {
        bool IsFolderTrusted(string absoluteFolderPath);

        void AddFolderToTrusted(string absoluteFolderPath);
    }
}
        private IWorkspaceTrustService workspaceTrustService;

        /// <summary>
        /// Gets solution service.
        /// </summary>
        public IWorkspaceTrustService WorkspaceTrustService => this.workspaceTrustService;

                this.workspaceTrustService = new WorkspaceTrustService(this.UserStorageSettingsService);
    using Community.VisualStudio.Toolkit;
    using Microsoft.VisualStudio.Shell.Interop;
    using Snyk.VisualStudio.Extension.Shared.UI;
                var isFolderTrusted = await this.IsFolderTrustedAsync();
                if (!isFolderTrusted)
                {
                    Logger.Information("Workspace folder was not trusted for scanning.");
                    return;
                }

        /// <summary>
        /// Checks if opened solution folder is trusted. If not, prompts a user with trust permission.
        /// </summary>
        /// <returns>Folder is trusted or not.</returns>
        public async Task<bool> IsFolderTrustedAsync()
        {
            var solutionFolderPath = await this.serviceProvider.SolutionService.GetSolutionFolderAsync();
            var isFolderTrusted = this.serviceProvider.WorkspaceTrustService.IsFolderTrusted(solutionFolderPath);

            if (string.IsNullOrEmpty(solutionFolderPath) || isFolderTrusted)
            {
                return true;
            }

            var trustDialog = new TrustDialogWindow(solutionFolderPath);
            var trusted = trustDialog.ShowModal();

            if (trusted != true)
            {
                return false;
            }

            try
            {
                this.serviceProvider.WorkspaceTrustService.AddFolderToTrusted(solutionFolderPath);
                Logger.Information("Workspace folder was trusted: {SolutionFolderPath}", solutionFolderPath);
                return true;
            }
            catch (ArgumentException e)
            {
                Logger.Error(e, "Failed to add folder to trusted list.");
                throw;
            }
        }

﻿namespace Snyk.VisualStudio.Extension.Shared.Service
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using Serilog;
    using Snyk.Common;
    using Snyk.VisualStudio.Extension.Shared.Settings;

    public class WorkspaceTrustService : IWorkspaceTrustService
    {
        private static readonly ILogger Logger = LogManager.ForContext<WorkspaceTrustService>();

        private readonly IUserStorageSettingsService settingsService;

        public WorkspaceTrustService(IUserStorageSettingsService settingsService)
        {
            this.settingsService = settingsService;
        }

        public void AddFolderToTrusted(string absoluteFolderPath)
        {
            if (!Path.IsPathRooted(absoluteFolderPath))
            {
                throw new ArgumentException("Trusted folder path provided is not absolute.");
            }

            if (!Directory.Exists(absoluteFolderPath))
            {
                throw new ArgumentException("Trusted folder doesn't exist.");
            }

            try
            {
                var trustedFolders = this.settingsService.TrustedFolders;
                trustedFolders.Add(absoluteFolderPath);
                this.settingsService.TrustedFolders = trustedFolders;
            }
            catch (Exception e)
            {
                Logger.Error(e, "Failed to add a folder to trusted.");
            }
        }

        public bool IsFolderTrusted(string absoluteFolderPath)
        {
            var trustedFolders = this.settingsService.TrustedFolders;

            foreach (var trustedFolder in trustedFolders)
            {
                if (this.IsSubFolderOrEqual(trustedFolder, absoluteFolderPath))
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Verify if subfolder is rooted at parent path.
        /// </summary>
        /// <param name="parentPath">Parent path to check against.</param>
        /// <param name="childPath">Subfolder path to verify.</param>
        /// <returns>Returns true if childPath is subfolder of parentPath, or equal to it.</returns>
        private bool IsSubFolderOrEqual(string parentPath, string childPath)
        {
            var parentUri = new Uri(parentPath);
            if (new Uri(childPath).Equals(parentUri))
            {
                return true;
            }

            var childUri = new DirectoryInfo(childPath).Parent;
            while (childUri != null)
            {
                if (new Uri(childUri.FullName).Equals(parentUri))
                {
                    return true;
                }

                childUri = childUri.Parent;
            }

            return false;
        }
    }
}
﻿namespace Snyk.VisualStudio.Extension.Shared.Settings
{
    using System.Collections.Generic;

    public interface IUserStorageSettingsService
    {
        ISet<string> TrustedFolders { get; set; }
    }
}
        /// Gets or sets the value of the custom CLI path.

        /// <summary>
        /// Gets or sets an array of workspace trusted folders.
        /// </summary>
        public ISet<string> TrustedFolders { get; set; } = new HashSet<string>();
    using System.Collections.Generic;
    public class SnykUserStorageSettingsService : IUserStorageSettingsService
        /// <summary>
        /// Gets or sets trusted folders list.
        /// </summary>
        public ISet<string> TrustedFolders
        {
            get => this.LoadSettings().TrustedFolders;
            set
            {
                var settings = this.LoadSettings();
                settings.TrustedFolders = value;
                this.settingsLoader.Save(settings);
            }
        }

    <Compile Include="$(MSBuildThisFileDirectory)Service\IWorkspaceTrustService.cs" />
    <Compile Include="$(MSBuildThisFileDirectory)Service\WorkspaceTrustService.cs" />
    <Compile Include="$(MSBuildThisFileDirectory)Settings\IUserStorageSettingsService.cs" />
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:c="clr-namespace:Snyk.VisualStudio.Extension.Shared.UI.Controls"
             mc:Ignorable="d"


                    2. Analyze code for issues and vulnerabilities
                <TextBlock Margin="0,10,0,0" TextWrapping="Wrap" Width="550">
                    When scanning project files, Snyk may automatically execute code such as invoking the package manager to get dependency information. You should only scan projects you trust.
                    <Hyperlink NavigateUri="https://docs.snyk.io/ide-tools/visual-studio-extension/workspace-trust" RequestNavigate="Hyperlink_RequestNavigate">
                        More info
                    </Hyperlink>
                </TextBlock>
                        Trust project and scan
                <TextBlock FontSize="11">
    using System;
    using Community.VisualStudio.Toolkit;
    using Microsoft.VisualStudio.Shell.Interop;
    using Serilog;
    using Serilog.Core;
    using Snyk.Common;
        private static readonly ILogger Logger = LogManager.ForContext<MessagePanel>();
            // Add folder to trusted
            var solutionFolderPath = await this.ServiceProvider.SolutionService.GetSolutionFolderAsync();
            if (!string.IsNullOrEmpty(solutionFolderPath))
            {
                try
                {
                    this.ServiceProvider.WorkspaceTrustService.AddFolderToTrusted(solutionFolderPath);
                    Logger.Information("Workspace folder was trusted: {SolutionFolderPath}", solutionFolderPath);
                }
                catch (ArgumentException ex)
                {
                    Logger.Error(ex, "Failed to add folder to trusted list.");
                    throw ex;
                }
            }

            // Issue scan
            if (authenticationSucceeded)
            {
                var uiShell = Microsoft.VisualStudio.Shell.ServiceProvider.GlobalProvider.GetService(typeof(SVsUIShell)) as IVsUIShell;
                if (uiShell != null)
                {
                    uiShell.PostExecCommand(
                        SnykGuids.SnykVSPackageCommandSet,
                        SnykGuids.RunScanCommandId,
                        0,
                        null);
                }
            }

﻿namespace Snyk.VisualStudio.Extension.Tests.Service
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using Moq;
    using Snyk.VisualStudio.Extension.Shared.Service;
    using Snyk.VisualStudio.Extension.Shared.Settings;
    using Xunit;

    public class WorkspaceTrustServiceTest
    {
        [Fact]
        public void WorkspaceTrustServiceTest_IsFolderTrusted_NotTrusted()
        {
            var trustedFolders = new HashSet<string>();
            var settingsServiceMock = new Mock<IUserStorageSettingsService>();
            settingsServiceMock.Setup(s => s.TrustedFolders).Returns(trustedFolders);

            var service = new WorkspaceTrustService(settingsServiceMock.Object);
            var folderPath = "C:\\Users\\Project";

            Assert.False(service.IsFolderTrusted(folderPath));
        }

        [Fact]
        public void WorkspaceTrustServiceTest_IsFolderTrusted_Trusted()
        {
            var trustedFolders = new HashSet<string>();
            trustedFolders.Add("C:\\Users\\Project");
            var settingsServiceMock = new Mock<IUserStorageSettingsService>();
            settingsServiceMock.Setup(s => s.TrustedFolders).Returns(trustedFolders);

            var service = new WorkspaceTrustService(settingsServiceMock.Object);
            var folderPath = "C:\\Users\\Project";

            Assert.True(service.IsFolderTrusted(folderPath));
        }

        [Fact]
        public void WorkspaceTrustServiceTest_IsFolderTrusted_SubfolderTrusted()
        {
            var trustedFolders = new HashSet<string>();
            trustedFolders.Add("C:\\Users\\Project");

            var settingsServiceMock = new Mock<IUserStorageSettingsService>();
            settingsServiceMock.Setup(s => s.TrustedFolders).Returns(trustedFolders);

            var service = new WorkspaceTrustService(settingsServiceMock.Object);
            var folderPath = "C:\\Users\\Project\\subfolder";

            Assert.True(service.IsFolderTrusted(folderPath));
        }

        [Fact]
        public void WorkspaceTrustServiceTest_IsFolderTrusted_ParentFolderNotTrusted()
        {
            var trustedFolders = new HashSet<string>();
            trustedFolders.Add("C:\\Users\\Project\\subfolder");

            var settingsServiceMock = new Mock<IUserStorageSettingsService>();
            settingsServiceMock.Setup(s => s.TrustedFolders).Returns(trustedFolders);

            var service = new WorkspaceTrustService(settingsServiceMock.Object);
            var folderPath = "C:\\Users\\Project";

            Assert.False(service.IsFolderTrusted(folderPath));
        }

        [Fact]
        public void WorkspaceTrustServiceTest_AddFolderToTrusted_NonExistingFolder()
        {
            var settingsServiceMock = new Mock<IUserStorageSettingsService>();

            var service = new WorkspaceTrustService(settingsServiceMock.Object);
            var folderPath = "C:\\Users\\Project";

            Assert.Throws<ArgumentException>(() => service.AddFolderToTrusted(folderPath));
        }

        [Fact]
        public void WorkspaceTrustServiceTest_AddFolderToTrusted_RelativeFolder()
        {
            var settingsServiceMock = new Mock<IUserStorageSettingsService>();

            var service = new WorkspaceTrustService(settingsServiceMock.Object);
            var folderPath = "\\Users\\Project";

            Assert.Throws<ArgumentException>(() => service.AddFolderToTrusted(folderPath));
        }

        [Fact]
        public void WorkspaceTrustServiceTest_AddFolderToTrusted_ExistingFolder()
        {
            var settingsServiceMock = new Mock<IUserStorageSettingsService>();
            settingsServiceMock.Setup(s => s.TrustedFolders).Returns(new HashSet<string>());

            var service = new WorkspaceTrustService(settingsServiceMock.Object);
            var folderPath = Path.GetDirectoryName(Path.GetTempFileName());

            service.AddFolderToTrusted(folderPath);

            settingsServiceMock.VerifySet(s => s.TrustedFolders = new HashSet<string> { folderPath }, Times.Once);
        }

        [Fact]
        public void WorkspaceTrustServiceTest_AddFolderToTrusted_MultipleFolders()
        {
            var settingsServiceMock = new Mock<IUserStorageSettingsService>();
            var presentFolder = "C:\\Users\\Project";
            settingsServiceMock.Setup(s => s.TrustedFolders).Returns(new HashSet<string> { presentFolder });

            var service = new WorkspaceTrustService(settingsServiceMock.Object);

            var newFolderPath = this.CreateTempDirectory();

            service.AddFolderToTrusted(newFolderPath);

            settingsServiceMock.VerifySet(s => s.TrustedFolders = new HashSet<string> { presentFolder, newFolderPath });
        }

        [Fact]
        public void WorkspaceTrustServiceTest_AddFolderToTrusted_SameFolderTwice()
        {
            var settingsServiceMock = new Mock<IUserStorageSettingsService>();
            settingsServiceMock.Setup(s => s.TrustedFolders).Returns(new HashSet<string>());
            var service = new WorkspaceTrustService(settingsServiceMock.Object);

            var folderPath1 = this.CreateTempDirectory();
            var folderPath2 = folderPath1;

            service.AddFolderToTrusted(folderPath1);
            settingsServiceMock.VerifySet(s => s.TrustedFolders = new HashSet<string> { folderPath1 }, Times.Once);

            service.AddFolderToTrusted(folderPath2);

            // Must not append new entry to collection
            settingsServiceMock.VerifySet(s => s.TrustedFolders = new HashSet<string> { folderPath1 }, Times.Exactly(2));
        }

        private string CreateTempDirectory()
        {
            var tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
            Directory.CreateDirectory(tempDirectory);

            return tempDirectory;
        }
    }
}
    <DeployVsixExtensionFilesDependsOn>$(DeployVsixExtensionFilesDependsOn);SaveSettingsJsonFile</DeployVsixExtensionFilesDependsOn>
  <ItemGroup>
    <Page Include="TrustDialogWindow.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </Page>
  </ItemGroup>
    <Compile Include="TrustDialogWindow.xaml.cs">
      <DependentUpon>TrustDialogWindow.xaml</DependentUpon>
    </Compile>
    <ItemGroup>
      <VSIXSourceItem Include="@(ReferencePath)" />
    </ItemGroup>
  <Target Name="SaveSettingsJsonFile" DependsOnTargets="GetVsixDeploymentPath">
    <Message Condition="!Exists('$(VsixDeploymentPath)settings.json')" Importance="High" Text="settings.json does not exist, skipping step" />
    <Message Condition="Exists('$(VsixDeploymentPath)settings.json')" Importance="High" Text="Saving settings.json file from $(VsixDeploymentPath)settings.json" />
    <Move Condition="Exists('$(VsixDeploymentPath)settings.json')" SourceFiles="$(VsixDeploymentPath)settings.json" DestinationFiles="$(IntermediateOutputPath)settings.json" />
  <Target Name="AfterBuild" DependsOnTargets="GetVsixDeploymentPath">
    <Message Condition="Exists('$(IntermediateOutputPath)settings.json')" Text="Copying settings.json back to $(VsixDeploymentPath)" Importance="High" />
    <Move Condition="Exists('$(IntermediateOutputPath)settings.json')" DestinationFiles="$(VsixDeploymentPath)settings.json" SourceFiles="$(IntermediateOutputPath)settings.json" />
﻿<ui:DialogWindow x:Class="Snyk.VisualStudio.Extension.TrustDialogWindow"
                 x:Name="trustDialogWindow"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:toolkit="clr-namespace:Community.VisualStudio.Toolkit;assembly=Community.VisualStudio.Toolkit"
                 xmlns:ui="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.14.0"
                 mc:Ignorable="d"
                 WindowStartupLocation="CenterScreen"
                 IsCloseButtonEnabled="True"
                 HasHelpButton="False"
                MinHeight="290" Height="290"
                 MinWidth="500" Width="500"
                 BorderBrush="{x:Static SystemColors.WindowFrameBrush}" BorderThickness="1"
                 WindowStyle="None" ResizeMode="NoResize" AllowsTransparency="True"
                 xmlns:catalog="clr-namespace:Microsoft.VisualStudio.Imaging;assembly=Microsoft.VisualStudio.ImageCatalog"
                 xmlns:imaging="clr-namespace:Microsoft.VisualStudio.Imaging;assembly=Microsoft.VisualStudio.Imaging"
                 toolkit:Themes.UseVsTheme="True"
                 Title="Snyk - This folder has not been trusted"
                 MouseDown="TrustDialogWindow_OnMouseDown">
    <DockPanel Margin="10">
        <Button DockPanel.Dock="Top" HorizontalAlignment="Right" Click="DoNotTrustButton_OnClick" MinWidth="1" MinHeight="1" Width="35" Margin="0" Padding="0">
            <imaging:CrispImage Moniker="{x:Static catalog:KnownMonikers.Close}"/>
        </Button>
        <StackPanel HorizontalAlignment="Right" DockPanel.Dock="Bottom" Orientation="Horizontal">
            <Button x:Name="TrustButton" Margin="5, 5" Content="Trust folder and continue" Click="TrustButton_OnClick"/>
            <Button x:Name="DoNotTrustButton" Margin="5, 5" Content="Don't scan" Click="DoNotTrustButton_OnClick"/>
        </StackPanel>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="auto"/>
                <RowDefinition Height="auto"/>
            </Grid.RowDefinitions>
            <Grid Grid.Row="0">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="5*"/>
                </Grid.ColumnDefinitions>
                <imaging:CrispImage Grid.Column="0" Width="50" Moniker="{x:Static catalog:KnownMonikers.StatusSecurityWarning}"/>
                <StackPanel VerticalAlignment="Center" Grid.Column="1" Margin="0, 0, 5, 0">
                    <TextBlock FontSize="14">This folder has not been trusted:</TextBlock>
                    <TextBlock FontSize="14" FontWeight="Bold" TextWrapping="Wrap" Text="{Binding ElementName=TrustWindow, Path=FolderPath}"/>
                </StackPanel>
            </Grid>
            <StackPanel Grid.Row="1" Margin="5">
                <TextBlock TextWrapping="Wrap">
                    When scanning folder files for vulnerabilities, Snyk may automatically execute code such as invoking the package manager to get dependency information. You should only scan folders you trust.
                </TextBlock>
                <TextBlock>
                    <LineBreak/>
                    <Hyperlink NavigateUri="https://docs.snyk.io/ide-tools/visual-studio-extension/workspace-trust" RequestNavigate="Hyperlink_OnRequestNavigate">
                        More information
                    </Hyperlink>
                </TextBlock>
            </StackPanel>
        </Grid>
    </DockPanel>
</ui:DialogWindow>
﻿namespace Snyk.VisualStudio.Extension
{
    using System.Diagnostics;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Navigation;
    using Microsoft.VisualStudio.PlatformUI;

    /// <summary>
    /// Trusted dialog window for Visual Studio versions less than 2022.
    /// </summary>
    public partial class TrustDialogWindow : DialogWindow
    {
        public TrustDialogWindow(string folderPath)
        {
            this.FolderPath = folderPath;
            this.InitializeComponent();
        }

        public string FolderPath { get; }

        private void DoNotTrustButton_OnClick(object sender, RoutedEventArgs e)
        {
            this.DialogResult = false;
            this.Close();
        }

        private void TrustButton_OnClick(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
            this.Close();
        }

        private void Hyperlink_OnRequestNavigate(object sender, RequestNavigateEventArgs e)
        {
            Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri));
            e.Handled = true;
        }

        private void TrustDialogWindow_OnMouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ChangedButton == MouseButton.Left)
            {
                this.DragMove();
            }
        }
    }
}