From d1921a5b825bec70dbf282267e2f07d9ded76156 Mon Sep 17 00:00:00 2001 From: Joel Platek Date: Mon, 31 Aug 2026 16:18:53 +0800 Subject: [PATCH 1/2] Fix Domain Admin prerequisite under PowerShell 7 AD compat shim; release v1.3.3 Under PowerShell 7, an RSAT ActiveDirectory module that is not Core-native loads through the Windows PowerShell compatibility shim and returns deserialized objects, so SIDs come back as strings. Test-TierModelPrerequisites compared a deserialized SID against a live SecurityIdentifier, so the Domain Admin membership check never matched and reported "Domain Admin membership required for deployment operations" even for genuine Domain Admins. - Import the ActiveDirectory module with -SkipEditionCheck so PowerShell 7 loads it in-process (native objects, no deserialization) in both the module-availability check and the Domain Admin check. - Add a fail-fast guard that detects the compatibility-shim condition (the domain SID returned as a string) and stops with clear remediation, preventing a silent deployment that would resolve empty SIDs into URA/GPO policy. - Bump module version 1.3.2 -> 1.3.3 and the version-assertion tests. - Add a compat-shim unit test to Unit.Prerequisites.Tests.ps1 (automated suite 1,652 -> 1,653, 0 failures). Refresh README counts and docs/test-coverage.md (Test-TierModelPrerequisites 85.12% -> 85.40%). CHANGELOG entry for 1.3.3. Lab-validated end to end: full -FullDeployment with all -Include options and -EnableAuditing (707 actions, 0 errors, all SIDs resolving) plus a full audit (418 checks, COMPLIANT, 0 drift). Closes #47 --- CHANGELOG.md | 5 ++++ README.md | 8 +++---- docs/test-coverage.md | 8 ++++--- modules/TierModel/TierModel.psd1 | 2 +- .../public/Test-TierModelPrerequisites.ps1 | 23 +++++++++++++++++-- tests/Integration.Module.Tests.ps1 | 2 +- tests/Unit.ModuleManifest.Tests.ps1 | 4 ++-- tests/Unit.Prerequisites.Tests.ps1 | 14 +++++++++++ 8 files changed, 53 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7d5150..9245f92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.3.3] - 2026-08-31 + +### Fixed +- **Domain Admin prerequisite false-fails under the PowerShell 7 Windows PowerShell compatibility shim (issue #47)**: when `Test-TierModelPrerequisites` ran under PowerShell 7 with an RSAT ActiveDirectory module that is not Core-native (for example on a Windows Server 2016 host, or any host whose AD module edition forces the fallback), PowerShell loaded the module through the Windows PowerShell compatibility shim (WinPSCompatSession) and returned **deserialized** objects โ€” SIDs came back as strings, so the `Get-ADGroupMember | Where-Object { $_.SID -eq $currentUser.User }` membership check compared a deserialized SID against a live `SecurityIdentifier` and never matched. The prerequisite reported *"Domain Admin membership required for deployment operations"* even for a genuine Domain Admin. The ActiveDirectory module is now imported with `-SkipEditionCheck` so PowerShell 7 loads it in-process (native objects, no deserialization), and a fail-fast guard detects the compatibility-shim condition (domain SID returned as a string) and stops with clear remediation โ€” preventing a silent broken deployment in which SID resolution would have written empty principals into URA and GPO restricted-groups policy. Lab-validated: full `-FullDeployment -IncludeMsa -IncludeGmsa -IncludeDmsa -IncludeWinLaps -EnableAuditing` deploy (707 actions, 0 errors, all SIDs resolving) followed by a full audit (418 checks, COMPLIANT, 0 drift). + ## [1.3.2] - 2026-08-24 ### Added diff --git a/README.md b/README.md index da06232..7f6d4e8 100644 --- a/README.md +++ b/README.md @@ -42,18 +42,18 @@ To get started with TierModel, please refer to our comprehensive documentation: ## ๐Ÿงช Testing & Quality Assurance -**Current Test Status: โœ… 1,652 passing / 0 failures (100%)** *(Last run: 2026-08-24)* +**Current Test Status: โœ… 1,653 passing / 0 failures (100%)** *(Last run: 2026-08-31)* | Test Suite | Test Files | Test Cases | Status | Coverage | |------------|-----------|------------|--------|----------| -| **Unit Tests** | 22 files | 1,338 tests | โœ… All pass | **88.93%** | +| **Unit Tests** | 22 files | 1,339 tests | โœ… All pass | **88.93%** | | **Integration Tests** | 7 files | 314 tests | โœ… All pass | **88.93%** | | **Manual Integration Tests** | 1 file | 335 tests | โœ… 100% Pass | **N/A** | -| **Total** | **29 files** | **1,987 tests** | โœ… **100% passing** | **88.93%** | +| **Total** | **29 files** | **1,988 tests** | โœ… **100% passing** | **88.93%** | ### Test Coverage Highlights - โœ… **71/71** production files have comprehensive test coverage -- โœ… **1,652 / 1,652** automated test cases passing โ€” 0 failures (Pester 5.9.0, 2026-08-24) +- โœ… **1,653 / 1,653** automated test cases passing โ€” 0 failures (Pester 5.9.0, 2026-08-31) - โœ… **88.93%** overall Pester-measured command coverage (all files above 80% CI gate) - โœ… **New canonical-ACL resilience (#41):** OU deploy uses a phased verify-and-remediate loop โ€” after each disable-inheritance write, `New-TierModelOu` reads back the DACL and auto-sorts if non-canonical (via `Repair-TierModelCanonicalAcl`); lab-validated at 7/7 OUs corrected per deploy under an inherited-Deny condition. New public cmdlet `Repair-TierModelCanonicalAcl` (**95.40%** coverage) available for standalone use. `Audit-TierModel.ps1` now reports Case 1 (non-canonical domain root, deployment blocker) and Case 2 (non-canonical Tier OU, pre-fix artifact) as structured drift findings. - โœ… **New in v1.3.0:** `-EnableAuditing` domain audit rule (SACL) support โ€” 4 new cmdlets (`Get-TierModelAuditRule` **100%**, `Get-TierModelAuditRuleFd` **97.73%**, `Test-TierModelAuditRule` **98.41%**, `New-TierModelAuditRule` **84.14%**) covered by `Unit.AuditRuleOperations.Tests.ps1` (47 unit tests) plus `-EnableAuditing` integration tests in Audit and Deploy orchestrators; `Audit-TierModel.ps1` **77.16%**, `Deploy-TierModel.ps1` **81.53%** diff --git a/docs/test-coverage.md b/docs/test-coverage.md index f705b3c..df00334 100644 --- a/docs/test-coverage.md +++ b/docs/test-coverage.md @@ -9,7 +9,9 @@ > **How coverage is measured:** Pester v5's built-in `CodeCoverage` feature instruments each production file and tracks which lines are executed during the full test suite run (`Invoke-AllTests.ps1`). To re-run: `cd TierModel; $c = New-PesterConfiguration; $c.Run.Path = './tests'; $c.CodeCoverage.Enabled = $true; $c.CodeCoverage.Path = @('./modules/TierModel/public/*.ps1','./modules/TierModel/TierModel.psm1','./Audit-TierModel.ps1','./Deploy-TierModel.ps1'); Invoke-Pester -Configuration $c` -**Last measured:** 2026-08-24 (1,652 total tests: **1,652 passing / 0 failures โ€” 100%** โ€” Pester 5.9.0 pinned) | **Overall: 88.93%** | **Target: 95%** | **CI gate: 80%** +**Last measured:** 2026-08-31 (1,653 total tests: **1,653 passing / 0 failures โ€” 100%** โ€” Pester 5.9.0 pinned) | **Overall: 88.93%** | **Target: 95%** | **CI gate: 80%** + +> โœ… **v1.3.3 measured (2026-08-31 โ€” 100% pass rate):** Domain Admin prerequisite false-fail under the PowerShell 7 Windows PowerShell compatibility shim (issue #47) โ€” `Test-TierModelPrerequisites.ps1` now imports the ActiveDirectory module with `-SkipEditionCheck` (native in-process load, no deserialized objects) and adds a shim-detection guard that fails fast when AD returns deserialized (string) SIDs, preventing a silent broken URA/GPO deployment. `Test-TierModelPrerequisites.ps1` **85.12% โ†’ 85.40%** (421/493; +12 analyzed commands for the guard, all covered). New compat-shim unit test in `Unit.Prerequisites.Tests.ps1` (+1 unit test; automated suite 1,652 โ†’ 1,653). Module version **1.3.2 โ†’ 1.3.3**. Overall aggregate unchanged at ~88.93% (12 new covered commands out of ~15k); all module-scope files remain above the 80% CI gate. > โœ… **v1.3.2 measured (2026-08-24 โ€” 100% pass rate):** Human-readable deployment duration output (issue #34) โ€” new `Format-TierModelDuration.ps1` **100%** (11/11 commands) provides the four-tier `<1ms` / `Xms` / `Xs` / `Xm Ys` console format now used at the nine `Deploy-TierModel.ps1` `Duration:` sites (`Write-TierModelLog` lines stay raw ms). New test file `Unit.FormatDuration.Tests.ps1` (**23** unit tests, incl. banker's-rounding regression guards at 90000 / 119999 / 120000 ms), wiring-proof assertions added to `Integration.Deploy.Tests.ps1` (mock `2254 โ†’ "Duration: 2s"`, all-converged `โ†’ "<1ms"`, aggregate `140000 โ†’ "2m 20s"`), and a manifest verb-allowlist + export assertion in `Unit.ModuleManifest.Tests.ps1`. Module version **1.3.1 โ†’ 1.3.2**. Overall aggregate 88.98% โ†’ **88.93%** (full suite 1,627 โ†’ 1,652 tests; `Deploy-TierModel.ps1` 81.53% โ†’ 81.62% with the nine formatter call-sites); all module-scope files remain above the 80% CI gate. @@ -29,7 +31,7 @@ |------|-------|-------| | โœ… 100% | `Write-TierModelLog`, `Resolve-*` (4), `Test-TierModelOuExists`, `Test-TierModelGPO`, `Test-TierModelGroup`, `Test-TierModelGPOLink`, `Get-TierModelGroup`, `Test-TierModelAdmx`, `Get-TierModelGPOLink`, `Get-TierModelAuditRule`, `Format-TierModelDuration` | 14 | | ๐ŸŸก 90-99% | MSA/gMSA/dMSA ops (12 files), `Resolve-TierModelPrincipalSid`, `Resolve-DomainSpecificGuid`, `Copy/Get-TierModelAdmx`, `Get-TierModelUser`, `Test-TierModelGPOAudit`, `Get-TierModelConfig`, `New-TierModelGpo`, `Get-TierModelGpoFd`, `Get-TierModelGpo`, `Test-TierModelGPOContent`, `Get-TierModelGpoLinkFd`, `Get-TierModelOuAcl`, `Get-TierModelGroupFd`, `Get-TierModelOuAclFd`, `New-TierModelOuAcl`, `New-TierModelWinLapsAcl`, `Test-TierModelWinLapsDecryptor`, `Test-TierModelCanonicalAcl`, `Test-TierModelAuditRule`, `Get-TierModelAuditRuleFd`, `Repair-TierModelCanonicalAcl` | 35 | -| ๐ŸŸ  80-89% | `Audit-TierModel` (77.16% โ€” ByServer paths exempt), `Deploy-TierModel`, `New-Tier*` (incl. `New-TierModelOu` 84.86%), `New-TierModelAuditRule`, `Get-TierModel*Fd` variants, `Import-TierModelGpo`, `Test-TierModelOuAcl`, `TierModel.psm1`, `Get-TierModelWinLapsAcl`, `Get-TierModelWinLapsAclFd`, `Test-TierModelPrerequisites` (85.12%), `Test-TierModelWinLapsAcl` | 20 | +| ๐ŸŸ  80-89% | `Audit-TierModel` (77.16% โ€” ByServer paths exempt), `Deploy-TierModel`, `New-Tier*` (incl. `New-TierModelOu` 84.86%), `New-TierModelAuditRule`, `Get-TierModel*Fd` variants, `Import-TierModelGpo`, `Test-TierModelOuAcl`, `TierModel.psm1`, `Get-TierModelWinLapsAcl`, `Get-TierModelWinLapsAclFd`, `Test-TierModelPrerequisites` (85.40%), `Test-TierModelWinLapsAcl` | 20 | | ๐Ÿ”ด 50-79% | `Test-TierModelOu.ps1` (79.4%) | 1 | | ๐Ÿšจ 0-25% | **No critical gaps!** ๐ŸŽ‰ | 0 | @@ -41,7 +43,7 @@ | `modules/TierModel/public/Import-TierModelGpo.ps1` | 89 | 21 | 110 | ๐ŸŸ  80.9% โœฆ | | `Deploy-TierModel.ps1` | 1854 | 420 | 2274 | ๐ŸŸ  81.53% โœฆ | | `modules/TierModel/public/Get-TierModelWinLapsAcl.ps1` | โ€” | โ€” | 543 | ๐ŸŸ  81.6% | -| `modules/TierModel/public/Test-TierModelPrerequisites.ps1` | 409 | 72 | 481 | ๐ŸŸ  85.12% โœฆ | +| `modules/TierModel/public/Test-TierModelPrerequisites.ps1` | 421 | 72 | 493 | ๐ŸŸ  85.40% โœฆ | | `modules/TierModel/TierModel.psm1` | 581 | 122 | 703 | ๐ŸŸ  82.65% โœฆ | | `modules/TierModel/public/New-TierModelGptTmplContent.ps1` | 85 | 17 | 102 | ๐ŸŸ  83.3% | | `modules/TierModel/public/Get-TierModelWinLapsAclFd.ps1` | 383 | 76 | 459 | ๐ŸŸ  83.4% | diff --git a/modules/TierModel/TierModel.psd1 b/modules/TierModel/TierModel.psd1 index caef91f..b90309e 100644 --- a/modules/TierModel/TierModel.psd1 +++ b/modules/TierModel/TierModel.psd1 @@ -1,6 +1,6 @@ @{ RootModule = 'TierModel.psm1' - ModuleVersion = '1.3.2' + ModuleVersion = '1.3.3' GUID = 'b6a7c9f8-5e5d-4c7a-9b9e-2e2e9a4f6d10' Author = 'TierModel Team' CompanyName = 'Enterprise AD' diff --git a/modules/TierModel/public/Test-TierModelPrerequisites.ps1 b/modules/TierModel/public/Test-TierModelPrerequisites.ps1 index 55b0cba..34e5af7 100644 --- a/modules/TierModel/public/Test-TierModelPrerequisites.ps1 +++ b/modules/TierModel/public/Test-TierModelPrerequisites.ps1 @@ -288,7 +288,7 @@ function Test-TierModelPrerequisites { # If module was found but not loaded, try to import it to verify it works if (-not $loadedModule -and $installedModule) { try { - Import-Module $moduleName -ErrorAction Stop -Verbose:$false | Out-Null + Import-Module $moduleName -ErrorAction Stop -Verbose:$false -SkipEditionCheck | Out-Null try { Write-TierModelLog -Level Debug -Message "Successfully imported $moduleName module for validation" | Out-Null } catch { @@ -310,8 +310,27 @@ function Test-TierModelPrerequisites { # Check domain admin membership regardless of elevation for testing scenarios try { - Import-Module ActiveDirectory -ErrorAction SilentlyContinue -Verbose:$false | Out-Null + Import-Module ActiveDirectory -ErrorAction SilentlyContinue -Verbose:$false -SkipEditionCheck | Out-Null + $adShimDetected = $false if (Get-Module ActiveDirectory) { + # Guard: under PowerShell 7, an RSAT ActiveDirectory module that is not Core-native + # loads through the Windows PowerShell compatibility shim (WinPSCompatSession) and + # returns DESERIALIZED objects - SIDs come back as strings, so .SID.Value / .objectSid.Value + # resolve empty. That silently breaks SID resolution deployment-wide (URA and GPO + # restricted-groups principals resolve to nothing). Detect it by probing whether the + # domain SID comes back as a plain string (deserialized) instead of a SecurityIdentifier, + # and fail fast rather than deploy broken policy. + try { + $adDomainProbe = Get-ADDomain -Server $PreferredDc -ErrorAction Stop + if ($adDomainProbe.DomainSID -is [string]) { $adShimDetected = $true } + } catch { } + } + if ($adShimDetected) { + $result.Valid = $false + $null = $result.Errors.Add("ActiveDirectory module is loaded through the Windows PowerShell compatibility shim (deserialized objects); SID resolution would break URA and GPO deployment.") + $null = $result.Remediation.Add("Run the deployment from a host with a PowerShell 7-native RSAT ActiveDirectory module (Windows 11 / Windows Server 2022 or later), or run under Windows PowerShell 5.1.") + } + elseif (Get-Module ActiveDirectory) { $currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent() $domainAdmins = Get-ADGroup -Identity "Domain Admins" -Server $PreferredDc -ErrorAction SilentlyContinue diff --git a/tests/Integration.Module.Tests.ps1 b/tests/Integration.Module.Tests.ps1 index 2dda6a2..420c010 100644 --- a/tests/Integration.Module.Tests.ps1 +++ b/tests/Integration.Module.Tests.ps1 @@ -32,7 +32,7 @@ Describe 'TierModel Module Integration Tests' -Tag 'Integration', 'Module' { } It 'Module version is correct' { - $script:LoadedModule.Version.ToString() | Should -Be '1.3.2' + $script:LoadedModule.Version.ToString() | Should -Be '1.3.3' } It 'Module loads all public function files' { diff --git a/tests/Unit.ModuleManifest.Tests.ps1 b/tests/Unit.ModuleManifest.Tests.ps1 index a13f42e..e52414a 100644 --- a/tests/Unit.ModuleManifest.Tests.ps1 +++ b/tests/Unit.ModuleManifest.Tests.ps1 @@ -38,8 +38,8 @@ Describe 'TierModel Module Manifest' -Tag 'Unit', 'Manifest' { $script:Manifest.ModuleVersion | Should -Match '^\d+\.\d+\.\d+$' } - It 'Has current version 1.3.2' { - $script:Manifest.ModuleVersion | Should -Be '1.3.2' + It 'Has current version 1.3.3' { + $script:Manifest.ModuleVersion | Should -Be '1.3.3' } It 'Has valid GUID' { diff --git a/tests/Unit.Prerequisites.Tests.ps1 b/tests/Unit.Prerequisites.Tests.ps1 index 7179cbf..10b3334 100644 --- a/tests/Unit.Prerequisites.Tests.ps1 +++ b/tests/Unit.Prerequisites.Tests.ps1 @@ -259,6 +259,20 @@ Describe "TierModel Prerequisites Tests" -Tag 'Unit','Prereq' { # With Get-ADGroup returning null from BeforeEach, expect this remediation message $result.Remediation | Should -Contain "Ensure Domain Admins group exists and user is member of Domain Admins group" } + + It "Should fail fast when the AD module is loaded via the WinPS compatibility shim (deserialized objects)" -Tag 'Negative','DomainAdmin','CompatShim' { + # PowerShell 7 loads a non-Core-native RSAT AD module through the Windows PowerShell + # compatibility shim, which deserializes results so DomainSID comes back as a plain + # string instead of a SecurityIdentifier. The prerequisite check must detect this and + # fail fast rather than let deployment proceed and resolve empty SIDs into URA/GPO policy. + Mock Get-ADDomain { return @{ DNSRoot = 'test.contoso.com'; NetBIOSName = 'TEST'; DomainSID = 'S-1-5-21-1111111111-2222222222-3333333333' } } -ModuleName TierModel + + $result = Test-TierModelPrerequisites -PreferredDc 'MockDC.test.local' -DependenciesPath $validDepsFile + + $result.Valid | Should -Be $false + ($result.Errors -join ' ') | Should -Match 'Windows PowerShell compatibility shim' + ($result.Remediation -join ' ') | Should -Match 'PowerShell 7-native RSAT' + } } Context "Host OS Language Enforcement" -Tag 'Language','Prereq' { From b7a36724737af549d5137445610368d0cec917fb Mon Sep 17 00:00:00 2001 From: Joel Platek Date: Mon, 31 Aug 2026 16:19:12 +0800 Subject: [PATCH 2/2] Remove tracked root cspell.json; spelling config is personal in .vscode The cSpell dictionary was consolidated into .vscode/settings.json (personal, gitignored) per the note in that file. Removing the tracked root cspell.json makes the Code Spell Checker configuration personal-only rather than a shared repository dictionary. --- cspell.json | 232 ---------------------------------------------------- 1 file changed, 232 deletions(-) delete mode 100644 cspell.json diff --git a/cspell.json b/cspell.json deleted file mode 100644 index 890f229..0000000 --- a/cspell.json +++ /dev/null @@ -1,232 +0,0 @@ -{ - "version": "0.2", - "language": "en", - "words": [ - "accesscontroltype", - "accidently", - "ackages", - "ackup", - "activedirectoryrights", - "adfail", - "adml", - "ADMX", - "admxdir", - "admxnolocale", - "ADSI", - "adthrow", - "ADUC", - "Applocker", - "APPPOOL", - "appxbundle", - "appxupload", - "Auggie", - "azuredevops", - "badver", - "binlog", - "bitlocker", - "bkup", - "buildhelp", - "Chakra", - "checkin", - "checkmark", - "checkmarks", - "clippy", - "CLIUSR", - "CODEBUDDY", - "codegen", - "contoso", - "coveragexml", - "csdef", - "Dacl", - "dbmdl", - "dbproj", - "Decryptor", - "decryptors", - "dedup", - "Descendents", - "DIALUP", - "Directorysecurityinheritance", - "dlldata", - "Dmsa", - "docstates", - "DSRM", - "duser", - "ebug", - "elease", - "eleases", - "esult", - "fabrikam", - "Fody", - "Fractors", - "gmsa", - "gpload", - "GPMC", - "gpoplan", - "GPORG", - "gpos", - "GPOURA", - "Groot", - "groupcategory", - "groupname", - "groupscope", - "hashtable", - "hashtables", - "healthcheck", - "healthchecksdb", - "helmignore", - "Helpdesk", - "himds", - "HKLM", - "htadmx", - "hyperv", - "identityreference", - "IDGUID", - "Infoblox", - "Installshield", - "iobj", - "ionide", - "Ionide", - "ipch", - "ipdb", - "IUSR", - "IUSRS", - "jmconfig", - "Keypackage", - "kilocode", - "kubeconfig", - "Kusto", - "Lanman", - "LASTEXITCODE", - "LDIF", - "linkplan", - "localhistory", - "logissue", - "lync", - "Memberof", - "mfractor", - "missingprop", - "missingsubprop", - "mkdocs", - "MMYY", - "Modelv", - "msedgeupdate", - "msedgewebview", - "msix", - "MSSQLFD", - "Netbios", - "nfrontend", - "nofiles", - "nolang", - "nolocale", - "noversion", - "npmignore", - "Nsight", - "ntests", - "NTFS", - "ntvs", - "nunit", - "nvuser", - "objectclass", - "objecttype", - "OLAP", - "onent", - "opencode", - "opendb", - "opensdf", - "opensource", - "OPTOUT", - "outlk", - "packrat", - "paket", - "Paket", - "parallelizable", - "pawdomainjoin", - "pidb", - "preflights", - "prereq", - "Prereqs", - "psadmx", - "psess", - "psmodules", - "psobject", - "PTVS", - "publishproj", - "publishsettings", - "pwsh", - "pycache", - "pytest", - "qwen", - "renv", - "resolveguid", - "retryable", - "rlib", - "RODC", - "rollouts", - "Rproj", - "rptproj", - "RSAT", - "rsuser", - "Ruserdata", - "samaccountname", - "SASTELEMETRY", - "schemaview", - "scriptanalyzer", - "scriptblock", - "SDDL", - "servicescode", - "SIEM", - "Silverlight", - "snupkg", - "speckit", - "SQLSERVERAGENT", - "SQLTELEMETRY", - "srvdomainjoin", - "SSISTELEMETRY", - "STIG", - "svclog", - "swiftpm", - "SYSVOL", - "tadmin", - "tdisabled", - "Telerik's", - "terraformignore", - "testdata", - "testdc", - "TESTDOMAIN", - "testuser", - "tfstate", - "tfvars", - "tierlab", - "tiermodel", - "timestamptest", - "TKTK", - "tlog", - "Tmpl", - "toplevel", - "topsecret", - "touchpoints", - "tuser", - "TXXX", - "ublish", - "uild", - "Underspecification", - "underspecified", - "userosscache", - "userpass", - "userprefs", - "USERPROFILE", - "venv", - "visio", - "vshistory", - "vspscc", - "vspx", - "vssscc", - "windowslaps", - "winlaps", - "wpftmp", - "wwwroot", - "xpress", - "ZZZNOMATCH" - ], - "flagWords": [] -}