diff --git a/.github/actions/spelling/expect/expect.txt b/.github/actions/spelling/expect/expect.txt index 32c182c8e4..ee8d15ee8f 100644 --- a/.github/actions/spelling/expect/expect.txt +++ b/.github/actions/spelling/expect/expect.txt @@ -943,6 +943,7 @@ gset gsl GTP GTR +guardxfg guc gui guidatom @@ -1802,6 +1803,7 @@ PNTSTATUS POBJECT Podcast POINTSLIST +Poli POLYTEXTW popd POPF @@ -2826,6 +2828,7 @@ xdy XEncoding xes xff +xfg XFile XFORM XManifest diff --git a/build/config/PolicheckExclusions.xml b/build/config/PolicheckExclusions.xml new file mode 100644 index 0000000000..a30447631c --- /dev/null +++ b/build/config/PolicheckExclusions.xml @@ -0,0 +1,11 @@ + + + + winrt|.git|oss|packages + + + + .PNG|.SVG|.BMP|.ICO + + + \ No newline at end of file diff --git a/build/pipelines/release.yml b/build/pipelines/release.yml index 3dd772210b..1bcf0c601b 100644 --- a/build/pipelines/release.yml +++ b/build/pipelines/release.yml @@ -18,6 +18,10 @@ parameters: displayName: "Build Windows Terminal MSIX" type: boolean default: true + - name: runCompliance + displayName: "Run Compliance and Security Build" + type: boolean + default: true - name: buildTerminalVPack displayName: "Build Windows Terminal VPack" type: boolean @@ -34,7 +38,6 @@ parameters: - Optimize - Instrument - None - - name: buildConfigurations type: object default: @@ -65,11 +68,11 @@ jobs: BuildConfiguration: ${{ config }} BuildPlatform: ${{ platform }} displayName: Build + timeoutInMinutes: 240 cancelTimeoutInMinutes: 1 steps: - checkout: self clean: true - fetchDepth: 1 submodules: true persistCredentials: True - task: PkgESSetupBuild@12 @@ -90,6 +93,7 @@ jobs: displayName: Use NuGet 5.10 inputs: versionSpec: 5.10 + - task: NuGetAuthenticate@0 # In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous. # This should be `task: NuGetCommand@2` - task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2 @@ -156,6 +160,7 @@ jobs: - ${{ if eq(parameters.buildTerminal, true) }}: - task: VSBuild@1 displayName: Build solution **\OpenConsole.sln + condition: true inputs: solution: '**\OpenConsole.sln' vsVersion: 16.0 @@ -196,8 +201,6 @@ jobs: filePath: build\scripts\Index-Pdbs.ps1 arguments: -SearchDir '$(Build.SourcesDirectory)' -SourceRoot '$(Build.SourcesDirectory)' -recursive -Verbose -CommitId $(Build.SourceVersion) errorActionPreference: silentlyContinue - - task: ComponentGovernanceComponentDetection@0 - displayName: Component Detection - task: PowerShell@2 displayName: Run Unit Tests condition: and(succeeded(), or(eq(variables['BuildPlatform'], 'x64'), eq(variables['BuildPlatform'], 'x86'))) @@ -254,6 +257,7 @@ jobs: inputs: PathtoPublish: $(Build.ArtifactStagingDirectory)/wpf ArtifactName: wpf-dll-$(BuildPlatform)-$(BuildConfiguration) + - task: PublishSymbols@2 displayName: Publish symbols path continueOnError: True @@ -265,6 +269,9 @@ jobs: IndexSources: false SymbolServerType: TeamServices +- ${{ if eq(parameters.runCompliance, true) }}: + - template: ./templates/build-console-compliance-job.yml + - ${{ if eq(parameters.buildTerminal, true) }}: - job: BundleAndSign displayName: Create and sign AppX/MSIX bundles diff --git a/build/pipelines/templates/build-console-compliance-job.yml b/build/pipelines/templates/build-console-compliance-job.yml new file mode 100644 index 0000000000..ea42382193 --- /dev/null +++ b/build/pipelines/templates/build-console-compliance-job.yml @@ -0,0 +1,224 @@ +jobs: +- job: Compliance + # We don't *need* a matrix but there's no other way to set parameters on a "job" + # in the AzDO YAML syntax. It would have to be a "stage" or a "template". + # Doesn't matter. We're going to do compliance on Release x64 because + # that's the one all the tooling works against for sure. + strategy: + matrix: + Release_x64: + BuildConfiguration: Release + BuildPlatform: x64 + displayName: Validate Security and Compliance + timeoutInMinutes: 240 + steps: + - checkout: self + clean: true + submodules: true + persistCredentials: True + - task: PkgESSetupBuild@12 + displayName: Package ES - Setup Build + inputs: + disableOutputRedirect: true + - task: PowerShell@2 + displayName: Rationalize Build Platform + inputs: + targetType: inline + script: >- + $Arch = "$(BuildPlatform)" + + If ($Arch -Eq "x86") { $Arch = "Win32" } + + Write-Host "##vso[task.setvariable variable=RationalizedBuildPlatform]${Arch}" + - task: NuGetToolInstaller@1 + displayName: Use NuGet 5.10 + inputs: + versionSpec: 5.10 + - task: NuGetAuthenticate@0 + # In the Microsoft Azure DevOps tenant, NuGetCommand is ambiguous. + # This should be `task: NuGetCommand@2` + - task: 333b11bd-d341-40d9-afcf-b32d5ce6f23b@2 + displayName: Restore NuGet packages for extraneous build actions + inputs: + command: restore + feedsToUse: config + configPath: NuGet.config + restoreSolution: build/packages.config + restoreDirectory: '$(Build.SourcesDirectory)\packages' + - task: NuGetCommand@2 + displayName: NuGet custom + inputs: + command: custom + selectOrConfig: config + nugetConfigPath: NuGet.Config + arguments: restore OpenConsole.sln -SolutionDirectory $(Build.SourcesDirectory) + - task: UniversalPackages@0 + displayName: Download terminal-internal Universal Package + inputs: + feedListDownload: 2b3f8893-a6e8-411f-b197-a9e05576da48 + packageListDownload: e82d490c-af86-4733-9dc4-07b772033204 + versionListDownload: $(TerminalInternalPackageVersion) + - task: TouchdownBuildTask@1 + displayName: Download Localization Files + inputs: + teamId: 7105 + authId: $(TouchdownAppId) + authKey: $(TouchdownAppKey) + resourceFilePath: >- + src\cascadia\TerminalApp\Resources\en-US\Resources.resw + + src\cascadia\TerminalControl\Resources\en-US\Resources.resw + + src\cascadia\TerminalConnection\Resources\en-US\Resources.resw + + src\cascadia\TerminalSettingsModel\Resources\en-US\Resources.resw + + src\cascadia\TerminalSettingsEditor\Resources\en-US\Resources.resw + + src\cascadia\WindowsTerminalUniversal\Resources\en-US\Resources.resw + + src\cascadia\CascadiaPackage\Resources\en-US\Resources.resw + appendRelativeDir: true + localizationTarget: false + pseudoSetting: Included + - task: PowerShell@2 + displayName: Move Loc files one level up + inputs: + targetType: inline + script: >- + $Files = Get-ChildItem . -R -Filter 'Resources.resw' | ? FullName -Like '*en-US\*\Resources.resw' + + $Files | % { Move-Item -Verbose $_.Directory $_.Directory.Parent.Parent -EA:Ignore } + pwsh: true + + # 1ES Component Governance onboarding (Detects open source components). See https://docs.opensource.microsoft.com/tools/cg.html + - task: ms.vss-governance-buildtask.governance-build-task-component-detection.ComponentGovernanceComponentDetection@0 + displayName: Component Detection + + # # PREfast and PoliCheck need Node. Install that first. + - task: NodeTool@0 + + # !!! NOTE !!! Run PREfast first. Some of the other tasks are going to run on a completed build. + # PREfast is going to build the code as a part of its analysis and the generated sources + # and output binaries will be sufficient for the rest of the analysis. + # If you disable this, the other tasks won't likely work. You would have to add a build + # step instead that builds the code normally before calling them. + # Also... PREfast will rebuild anyway so that's why we're not running a normal build first. + # Waste of time to build twice. + # PREfast. See https://www.1eswiki.com/wiki/SDL_Native_Rules_Build_Task + + # The following 1ES tasks all operate completely differently and have a different syntax for usage. + # Most notable is every one of them has a different way of excluding things. + # Go see their 1eswiki.com pages to figure out how to exclude things. + # When writing exclusions, try to make them narrow so when new projects/binaries are added, they + # cause an error here and have to be explicitly pulled out. Don't write an exclusion so broad + # that it will catch other new stuff. + + # https://www.1eswiki.com/wiki/PREfast_Build_Task + # Builds the project with C/C++ static analysis tools to find coding flaws and vulnerabilities + # !!! WARNING !!! It doesn't work with WAPPROJ packaging projects. Build the sub-projects instead. + - task: securedevelopmentteam.vss-secure-development-tools.build-task-prefast.SDLNativeRules@3 + displayName: 'Run the PREfast SDL Native Rules for MSBuild' + condition: succeededOrFailed() + inputs: + msBuildCommandline: msbuild.exe /nologo /m /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }} /p:WindowsTerminalReleaseBuild=true /p:platform=$(BuildPlatform) /p:configuration=$(BuildConfiguration) /t:Terminal\Window\WindowsTerminal /p:VisualStudioVersion=16.0 $(Build.SourcesDirectory)\OpenConsole.sln + + # Copies output from PREfast SDL Native Rules task to expected location for consumption by PkgESSecComp + - task: CopyFiles@1 + displayName: 'Copy PREfast xml files to SDLNativeRulesDir' + inputs: + SourceFolder: '$(Agent.BuildDirectory)' + Contents: | + **\*.nativecodeanalysis.xml + TargetFolder: '$(Agent.BuildDirectory)\_sdt\logs\SDLNativeRules' + + # https://www.1eswiki.com/index.php?title=PoliCheck_Build_Task + # Scans the text of source code, comments, and content for terminology that could be sensitive for legal, cultural, or geopolitical reasons. + # (Also finds vulgarities... takes all the fun out of everything.) + - task: securedevelopmentteam.vss-secure-development-tools.build-task-policheck.PoliCheck@2 + displayName: 'Run PoliCheck' + inputs: + targetType: F + targetArgument: $(Build.SourcesDirectory) + result: PoliCheck.xml + optionsFC: 1 + optionsXS: 1 + optionsUEPath: $(Build.SourcesDirectory)\build\config\PolicheckExclusions.xml + optionsHMENABLE: 0 + continueOnError: true + + # https://www.1eswiki.com/wiki/CredScan_Azure_DevOps_Build_Task + # Searches through source code and build outputs for a credential left behind in the open + - task: securedevelopmentteam.vss-secure-development-tools.build-task-credscan.CredScan@3 + displayName: 'Run CredScan' + inputs: + outputFormat: pre + # suppressionsFile: LocalSuppressions.json + batchSize: 20 + debugMode: false + continueOnError: true + + # https://www.1eswiki.com/wiki/BinSkim_Build_Task + # Searches managed and unmanaged binaries for known security vulnerabilities. + - task: securedevelopmentteam.vss-secure-development-tools.build-task-binskim.BinSkim@4 + displayName: 'Run BinSkim' + inputs: + TargetPattern: guardianGlob + # See https://aka.ms/gdn-globs for how to do match patterns + AnalyzeTargetGlob: $(Build.SourcesDirectory)\bin\**\*.dll;$(Build.SourcesDirectory)\bin\**\*.exe;-:file|**\Microsoft.UI.Xaml.dll;-:file|**\Microsoft.Toolkit.Win32.UI.XamlHost.dll;-:file|**\vcruntime*.dll;-:file|**\vcomp*.dll;-:file|**\vccorlib*.dll;-:file|**\vcamp*.dll;-:file|**\msvcp*.dll;-:file|**\concrt*.dll;-:file|**\TerminalThemeHelpers*.dll;-:file|**\cpprest*.dll + continueOnError: true + + # Set XES_SERIALPOSTBUILDREADY to run Security and Compliance task once per build + - powershell: Write-Host “##vso[task.setvariable variable=XES_SERIALPOSTBUILDREADY;]true” + displayName: 'Set XES_SERIALPOSTBUILDREADY Vars' + + # https://www.osgwiki.com/wiki/Package_ES_Security_and_Compliance + # Does a few things: + # - Ensures that Windows-required compliance tasks are run either inside this task + # or were run as a previous step prior to this one + # (PREfast, PoliCheck, Credscan) + # - Runs Windows-specific compliance tasks inside the task + # + CheckCFlags - ensures that compiler and linker flags meet Windows standards + # + CFGCheck/XFGCheck - ensures that Control Flow Guard (CFG) or + # eXtended Flow Guard (XFG) are enabled on binaries + # NOTE: CFG is deprecated and XFG isn't fully ready yet. + # NOTE2: CFG fails on an XFG'd binary + # - Brokers all security/compliance task logs to "Trust Services Automation (TSA)" (https://aka.ms/tsa) + # which is a system that maps all errors into the appropriate bug database + # template for each organization since they all vary. It should also suppress + # new bugs when one already exists for the product. + # This one is set up to go to the OS repository and use the given parameters + # to file bugs to our AzDO product path. + # If we don't use PkgESSecComp to do this for us, we need to install the TSA task + # ourselves in this pipeline to finalize data upload and bug creation. + # !!! NOTE !!! This task goes *LAST* after any other compliance tasks so it catches their logs + - task: PkgESSecComp@10 + displayName: 'Security and Compliance tasks' + inputs: + fileNewBugs: false + areaPath: 'OS\WDX\DXP\WinDev\Terminal' + teamProject: 'OS' + iterationPath: 'OS\Future' + bugTags: 'TerminalReleaseCompliance' + scanAll: true + errOnBugs: false + failOnStdErr: true + taskLogVerbosity: Diagnostic + secCompConfigFromTask: | + # Overrides default build sources directory + sourceTargetOverrideAll: $(Build.SourcesDirectory) + # Overrides default build binaries directory when "Scan all" option is specified + binariesTargetOverrideAll: $(Build.SourcesDirectory)\bin + + # Set the tools to false if they should not run in the build + tools: + - toolName: CheckCFlags + enable: true + - toolName: CFGCheck + enable: true + - toolName: Policheck + enable: false + - toolName: CredScan + enable: false + - toolName: XFGCheck + enable: false \ No newline at end of file diff --git a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp index 5c6d91a4d8..96ecaa9ac5 100644 --- a/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp +++ b/src/cascadia/TerminalSettingsModel/CascadiaSettings.cpp @@ -219,6 +219,18 @@ Model::Profile CascadiaSettings::CreateNewProfile() return *newProfile; } +template +static bool isProfilesDefaultsOrigin(const T& profile) +{ + return profile && profile.Origin() != winrt::Microsoft::Terminal::Settings::Model::OriginTag::ProfilesDefaults; +} + +template +static bool isProfilesDefaultsOriginSub(const T& sub) +{ + return sub && isProfilesDefaultsOrigin(sub.SourceProfile()); +} + // Method Description: // - Duplicate a new profile based off another profile's settings // - This differs from Profile::Copy because it also copies over settings @@ -250,14 +262,6 @@ Model::Profile CascadiaSettings::DuplicateProfile(const Model::Profile& source) const auto duplicated = _createNewProfile(newName); - static constexpr auto isProfilesDefaultsOrigin = [](const auto& profile) -> bool { - return profile && profile.Origin() != OriginTag::ProfilesDefaults; - }; - - static constexpr auto isProfilesDefaultsOriginSub = [](const auto& sub) -> bool { - return sub && isProfilesDefaultsOrigin(sub.SourceProfile()); - }; - #define NEEDS_DUPLICATION(settingName) source.Has##settingName() || isProfilesDefaultsOrigin(source.settingName##OverrideSource()) #define NEEDS_DUPLICATION_SUB(source, settingName) source.Has##settingName() || isProfilesDefaultsOriginSub(source.settingName##OverrideSource()) diff --git a/src/common.build.pre.props b/src/common.build.pre.props index fa65813ee6..30d7fb285f 100644 --- a/src/common.build.pre.props +++ b/src/common.build.pre.props @@ -168,6 +168,7 @@ true NDEBUG;%(PreprocessorDefinitions) false + %(AdditionalOptions) true