Refactor: Secure literal search and defensive scope handling (#4492)

* Refactor: Secure literal search and defensive scope handling

* Refactor: Secure literal search for Tweaks Tab

* Merge branch 'ChrisTitusTech:main' into fix-search-security
This commit is contained in:
Nazrul Islam
2026-05-19 23:56:58 +06:00
committed by GitHub
parent 522c4471c0
commit 743f9e3783
2 changed files with 376 additions and 118 deletions
@@ -3,13 +3,41 @@ function Find-AppsByNameOrDescription {
.SYNOPSIS
Searches through the Apps on the Install Tab and hides all entries that do not match the string
.DESCRIPTION
Filters application entries by name or description using literal string matching.
Respects collapsed category state and handles null $sync gracefully.
.PARAMETER SearchString
The string to be searched for
The string to be searched for. Wildcards are treated as literal characters.
.NOTES
- Uses module-scope $sync (no parameter needed; inherits from caller's scope)
- Performs literal matching (no wildcard expansion)
- Safely handles missing hashtable keys and null UI elements
- Protected by try/catch to prevent UI thread crashes
#>
param(
[Parameter(Mandatory = $false)]
[string]$SearchString = ""
)
# Validate that $sync exists and has required structure
if ($null -eq $sync) {
Write-Warning "Find-AppsByNameOrDescription: Global `$sync not found. Aborting search."
return
}
if ($null -eq $sync.ItemsControl) {
Write-Warning "Find-AppsByNameOrDescription: `$sync.ItemsControl not initialized. Aborting search."
return
}
if ($null -eq $sync.configs -or $null -eq $sync.configs.applicationsHashtable) {
Write-Warning "Find-AppsByNameOrDescription: `$sync.configs.applicationsHashtable not initialized. Aborting search."
return
}
try {
# Reset the visibility if the search string is empty or the search is cleared
if ([string]::IsNullOrWhiteSpace($SearchString)) {
$sync.ItemsControl.Items | ForEach-Object {
@@ -26,7 +54,8 @@ function Find-AppsByNameOrDescription {
# Respect the collapsed state of categories (indicated by + prefix)
if ($categoryLabel.Content -like "+*") {
$wrapPanel.Visibility = [Windows.Visibility]::Collapsed
} else {
}
else {
$wrapPanel.Visibility = [Windows.Visibility]::Visible
}
@@ -39,6 +68,9 @@ function Find-AppsByNameOrDescription {
return
}
# Escape wildcard characters for literal matching
$escapedSearchString = [System.Management.Automation.WildcardPattern]::Escape($SearchString)
# Perform search
$sync.ItemsControl.Items | ForEach-Object {
# Each item is a StackPanel container with Children[0] = label, Children[1] = WrapPanel
@@ -52,8 +84,20 @@ function Find-AppsByNameOrDescription {
# Search through apps in this category
$wrapPanel.Children | ForEach-Object {
$appEntry = $sync.configs.applicationsHashtable.$($_.Tag)
if ($appEntry.Content -like "*$SearchString*" -or $appEntry.Description -like "*$SearchString*") {
# Safely retrieve app entry from hashtable
$appTag = $_.Tag
$appEntry = $null
if (-not [string]::IsNullOrWhiteSpace($appTag) -and $sync.configs.applicationsHashtable.ContainsKey($appTag)) {
$appEntry = $sync.configs.applicationsHashtable[$appTag]
}
# Check if app matches search criteria
if ($null -ne $appEntry) {
$contentMatch = $appEntry.Content -like "*$escapedSearchString*"
$descriptionMatch = $appEntry.Description -like "*$escapedSearchString*"
if ($contentMatch -or $descriptionMatch) {
# Show the App and mark that this category has a match
$_.Visibility = [Windows.Visibility]::Visible
$categoryHasMatch = $true
@@ -62,6 +106,11 @@ function Find-AppsByNameOrDescription {
$_.Visibility = [Windows.Visibility]::Collapsed
}
}
else {
# Hide app if no entry found (data integrity issue)
$_.Visibility = [Windows.Visibility]::Collapsed
}
}
# If category has matches, show the WrapPanel and update the category label to expanded state
if ($categoryHasMatch) {
@@ -71,10 +120,17 @@ function Find-AppsByNameOrDescription {
if ($categoryLabel.Content -like "+*") {
$categoryLabel.Content = $categoryLabel.Content -replace "^\+ ", "- "
}
} else {
}
else {
# Hide the entire category container if no matches
$_.Visibility = [Windows.Visibility]::Collapsed
}
}
}
}
catch {
Write-Warning "Find-AppsByNameOrDescription: An error occurred during search: $_"
# Fail gracefully - do not crash the UI thread
return
}
}
@@ -3,98 +3,300 @@ function Find-TweaksByNameOrDescription {
.SYNOPSIS
Searches through the Tweaks on the Tweaks Tab and hides all entries that do not match the search string
.DESCRIPTION
Filters tweak entries by name or description using literal string matching (no wildcard expansion).
Respects collapsed category state and handles null $sync gracefully.
Safe for rapid keystroke events; no terminal spam on error conditions.
.PARAMETER SearchString
The string to be searched for
The string to be searched for. Wildcards are treated as literal characters.
.NOTES
- Uses module-scope $sync (resolved via global/script fallback if needed)
- Performs literal matching (no wildcard expansion)
- Safely handles missing UI elements and null properties
- Protected by try/catch to prevent UI thread crashes
- PowerShell 5.1 compatible (no ternary operators, no advanced language features)
#>
param(
[Parameter(Mandatory = $false)]
[string]$SearchString = ""
)
# Reset the visibility if the search string is empty or the search is cleared
if ([string]::IsNullOrWhiteSpace($SearchString)) {
# Show all categories
$tweakspanel = $sync.Form.FindName("tweakspanel")
$tweakspanel.Children | ForEach-Object {
$_.Visibility = [Windows.Visibility]::Visible
# ──────────────────────────────────────────────────────────────────────────────
# 1. RESOLVE $SYNC WITH MULTI-LEVEL FALLBACK
# ──────────────────────────────────────────────────────────────────────────────
# Foreach category section, show all items
if ($_ -is [Windows.Controls.Border]) {
$_.Visibility = [Windows.Visibility]::Visible
if ($null -eq $Sync) {
$Sync = $global:sync
if ($null -eq $Sync) {
$Sync = $script:sync
}
}
# Find ItemsControl
$dockPanel = $_.Child
if ($dockPanel -is [Windows.Controls.DockPanel]) {
$itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] }
if ($itemsControl) {
# Show items in the category
foreach ($item in $itemsControl.Items) {
if ($item -is [Windows.Controls.Label]) {
$item.Visibility = [Windows.Visibility]::Visible
} elseif ($item -is [Windows.Controls.DockPanel] -or
$item -is [Windows.Controls.StackPanel]) {
$item.Visibility = [Windows.Visibility]::Visible
}
}
}
}
}
}
# Validate that $Sync exists and has required structure
if ($null -eq $Sync) {
# Silent return - function called on every keystroke; no warning spam
return
}
# Search for matching tweaks when search string is not null
$tweakspanel = $sync.Form.FindName("tweakspanel")
if ($null -eq $Sync.Form) {
# Silent return - form not yet initialized
return
}
$tweakspanel.Children | ForEach-Object {
# ──────────────────────────────────────────────────────────────────────────────
# 2. GET REFERENCE TO TWEAKS PANEL
# ──────────────────────────────────────────────────────────────────────────────
$tweaksPanel = $null
try {
$tweaksPanel = $Sync.Form.FindName("tweakspanel")
}
catch {
# Silent return - panel not found or disposed
return
}
if ($null -eq $tweaksPanel) {
# Silent return - panel doesn't exist
return
}
# ──────────────────────────────────────────────────────────────────────────────
# 3. HANDLE EMPTY/WHITESPACE SEARCH STRING - RESET TO DEFAULT STATE
# ──────────────────────────────────────────────────────────────────────────────
if ([string]::IsNullOrWhiteSpace($SearchString)) {
try {
$tweaksPanel.Children | ForEach-Object {
$categoryBorder = $_
$categoryVisible = $false
if ($_ -is [Windows.Controls.Border]) {
# Find the ItemsControl
$dockPanel = $_.Child
# Safely set visibility
if ($null -ne $categoryBorder) {
$categoryBorder.Visibility = [Windows.Visibility]::Visible
}
# Process each category
if ($categoryBorder -is [Windows.Controls.Border]) {
$dockPanel = $null
if ($null -ne $categoryBorder.Child) {
$dockPanel = $categoryBorder.Child
}
if ($dockPanel -is [Windows.Controls.DockPanel]) {
$itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] }
if ($itemsControl) {
$itemsControl = $null
$itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] } | Select-Object -First 1
if ($null -ne $itemsControl) {
# Show all items in the category
foreach ($item in $itemsControl.Items) {
if ($null -ne $item) {
# Check if it's a category label (first Label in the ItemsControl)
if ($item -is [Windows.Controls.Label]) {
$item.Visibility = [Windows.Visibility]::Visible
}
elseif ($item -is [Windows.Controls.DockPanel] -or $item -is [Windows.Controls.StackPanel]) {
# Show all checkbox containers
$item.Visibility = [Windows.Visibility]::Visible
}
}
}
}
}
}
}
}
catch {
# Silent catch - UI element may be disposed
}
return
}
# ──────────────────────────────────────────────────────────────────────────────
# 4. PERFORM LITERAL SEARCH (NO WILDCARD EXPANSION)
# ──────────────────────────────────────────────────────────────────────────────
try {
# Normalize search term once for the entire operation
$searchTerm = $SearchString
if ($null -eq $searchTerm) {
$searchTerm = ""
}
# Iterate through all categories
$tweaksPanel.Children | ForEach-Object {
$categoryBorder = $_
$categoryHasMatch = $false
if ($categoryBorder -is [Windows.Controls.Border]) {
$dockPanel = $null
if ($null -ne $categoryBorder.Child) {
$dockPanel = $categoryBorder.Child
}
if ($dockPanel -is [Windows.Controls.DockPanel]) {
$itemsControl = $null
$itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] } | Select-Object -First 1
if ($null -ne $itemsControl) {
$categoryLabel = $null
# Process all items in the ItemsControl
# Process all items (checkboxes, labels, panels) in the ItemsControl
for ($i = 0; $i -lt $itemsControl.Items.Count; $i++) {
$item = $itemsControl.Items[$i]
if ($null -eq $item) {
continue
}
# ────────────────────────────────────────────────────────────
# Check if this is a category label (usually first Label)
# ────────────────────────────────────────────────────────────
if ($item -is [Windows.Controls.Label]) {
$categoryLabel = $item
# Initially hide category label; show it only if matches found
$item.Visibility = [Windows.Visibility]::Collapsed
} elseif ($item -is [Windows.Controls.DockPanel]) {
}
# ────────────────────────────────────────────────────────────
# Check if this is a DockPanel containing a tweak checkbox
# ────────────────────────────────────────────────────────────
elseif ($item -is [Windows.Controls.DockPanel]) {
$checkbox = $null
$label = $null
# Safely extract checkbox and label
$checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] } | Select-Object -First 1
$label = $item.Children | Where-Object { $_ -is [Windows.Controls.Label] } | Select-Object -First 1
if ($label -and ($label.Content -like "*$SearchString*" -or $label.ToolTip -like "*$SearchString*")) {
# Check if tweak matches search criteria
$itemMatches = $false
if ($null -ne $label) {
$labelContent = $label.Content
$labelToolTip = $label.ToolTip
# Safely null-check properties
if ($null -eq $labelContent) {
$labelContent = ""
}
if ($null -eq $labelToolTip) {
$labelToolTip = ""
}
# Convert to string and perform LITERAL matching
$labelContentStr = [string]$labelContent
$labelToolTipStr = [string]$labelToolTip
# Use IndexOf for literal matching (no wildcard interpretation)
$contentMatch = $labelContentStr.IndexOf($searchTerm, [System.StringComparison]::OrdinalIgnoreCase) -ge 0
$toolTipMatch = $labelToolTipStr.IndexOf($searchTerm, [System.StringComparison]::OrdinalIgnoreCase) -ge 0
if ($contentMatch -or $toolTipMatch) {
$itemMatches = $true
}
}
# Set visibility based on match result
if ($itemMatches) {
$item.Visibility = [Windows.Visibility]::Visible
if ($categoryLabel) { $categoryLabel.Visibility = [Windows.Visibility]::Visible }
$categoryVisible = $true
} else {
$categoryHasMatch = $true
}
else {
$item.Visibility = [Windows.Visibility]::Collapsed
}
} elseif ($item -is [Windows.Controls.StackPanel]) {
# StackPanel which contain checkboxes or other elements
}
# ────────────────────────────────────────────────────────────
# Check if this is a StackPanel containing a tweak checkbox
# ────────────────────────────────────────────────────────────
elseif ($item -is [Windows.Controls.StackPanel]) {
$checkbox = $null
$checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] } | Select-Object -First 1
if ($checkbox -and ($checkbox.Content -like "*$SearchString*" -or $checkbox.ToolTip -like "*$SearchString*")) {
$itemMatches = $false
if ($null -ne $checkbox) {
$checkboxContent = $checkbox.Content
$checkboxToolTip = $checkbox.ToolTip
# Safely null-check properties
if ($null -eq $checkboxContent) {
$checkboxContent = ""
}
if ($null -eq $checkboxToolTip) {
$checkboxToolTip = ""
}
# Convert to string and perform LITERAL matching
$checkboxContentStr = [string]$checkboxContent
$checkboxToolTipStr = [string]$checkboxToolTip
# Use IndexOf for literal matching (no wildcard interpretation)
$contentMatch = $checkboxContentStr.IndexOf($searchTerm, [System.StringComparison]::OrdinalIgnoreCase) -ge 0
$toolTipMatch = $checkboxToolTipStr.IndexOf($searchTerm, [System.StringComparison]::OrdinalIgnoreCase) -ge 0
if ($contentMatch -or $toolTipMatch) {
$itemMatches = $true
}
}
# Set visibility based on match result
if ($itemMatches) {
$item.Visibility = [Windows.Visibility]::Visible
if ($categoryLabel) { $categoryLabel.Visibility = [Windows.Visibility]::Visible }
$categoryVisible = $true
} else {
$categoryHasMatch = $true
}
else {
$item.Visibility = [Windows.Visibility]::Collapsed
}
}
}
# ────────────────────────────────────────────────────────────
# Update category label visibility and expanded/collapsed state
# ────────────────────────────────────────────────────────────
if ($categoryHasMatch) {
# Show category label
if ($null -ne $categoryLabel) {
$categoryLabel.Visibility = [Windows.Visibility]::Visible
# Update category label to expanded state (change "+" to "-")
$labelContent = $categoryLabel.Content
if ($null -ne $labelContent) {
$labelStr = [string]$labelContent
# Safe string replacement without -replace regex
if ($labelStr.StartsWith("+ ")) {
$expandedLabel = "- " + $labelStr.Substring(2)
$categoryLabel.Content = $expandedLabel
}
}
}
}
}
}
# Set the visibility based on if any item matched
$categoryBorder.Visibility = if ($categoryVisible) { [Windows.Visibility]::Visible } else { [Windows.Visibility]::Collapsed }
# ────────────────────────────────────────────────────────────────
# Set category border visibility based on whether it has matches
# ────────────────────────────────────────────────────────────────
if ($categoryHasMatch) {
$categoryBorder.Visibility = [Windows.Visibility]::Visible
}
else {
$categoryBorder.Visibility = [Windows.Visibility]::Collapsed
}
}
}
}
catch {
# Silent catch - UI elements may be disposed or in unexpected state
# Do not log to terminal as this function is called on every keystroke
}
}