Private/BrowserHistory.Firefox.ps1
|
# BrowserHistory.Firefox.ps1 - Firefox browser history scanning function Get-FirefoxHistory { <# .SYNOPSIS Parse Firefox browser history for AI usage indicators. .DESCRIPTION Scans Firefox browser history SQLite database (places.sqlite) for URLs matching known AI tools. Firefox uses a different database schema than Chromium-based browsers. Supports multiple profiles and handles locked database files. .PARAMETER DaysBack Number of days of history to scan. Default is 90. .PARAMETER AllUsers Scan all users on the system instead of just the current user. Requires elevated/admin permissions. .EXAMPLE Get-FirefoxHistory -DaysBack 30 .EXAMPLE Get-FirefoxHistory -AllUsers #> [CmdletBinding()] param( [int] $DaysBack = 90, [switch] $AllUsers ) Write-Verbose "Starting Firefox history scan..." $findings = @() # Get AI tool patterns $aiPatterns = Get-AIToolPatterns # Get Firefox profile paths $profiles = Get-BrowserProfilePaths -Browser 'Firefox' -AllUsers:$AllUsers if ($profiles.Count -eq 0) { Write-Verbose "No Firefox profiles found." return $findings } Write-Verbose "Found $($profiles.Count) Firefox profile(s)" foreach ($profile in $profiles) { Write-Verbose "Scanning Firefox profile: $($profile.ProfileName)" # Query the places database # Firefox stores URLs in moz_places with visits in moz_historyvisits $query = @" SELECT p.url, p.title, p.visit_count, p.last_visit_date FROM moz_places p WHERE p.last_visit_date IS NOT NULL AND p.url NOT LIKE 'place:%' ORDER BY p.last_visit_date DESC "@ $historyEntries = Invoke-SQLiteQuery -DatabasePath $profile.HistoryPath -Query $query if ($historyEntries.Count -eq 0) { Write-Verbose "No history entries found in profile: $($profile.ProfileName)" continue } Write-Verbose "Found $($historyEntries.Count) history entries in profile: $($profile.ProfileName)" foreach ($entry in $historyEntries) { $url = $entry.url if (-not $url) { continue } # Check against each AI pattern foreach ($pattern in $aiPatterns) { if ($url -match $pattern.Pattern) { # Convert timestamp $timestamp = $null if ($entry.last_visit_date) { try { $timestamp = Convert-FirefoxTimestamp -Timestamp ([long]$entry.last_visit_date) # Filter by DaysBack $cutoffDate = (Get-Date).AddDays(-$DaysBack) if ($timestamp -lt $cutoffDate) { continue } } catch { Write-Verbose "Failed to parse timestamp for URL: $url" } } $findings += [PSCustomObject]@{ Browser = 'Firefox' Username = $profile.Username Profile = $profile.ProfileName Tool = $pattern.Name Category = $pattern.Category Url = $url Title = $entry.title VisitCount = [int]$entry.visit_count Timestamp = $timestamp } # Only match first pattern per URL break } } } } Write-Verbose "Firefox scan complete. Found $($findings.Count) AI-related entries." return $findings } |