Use this workflow when the file-share environment is locked down, but reviewers need a richer dashboard experience on another workstation. The collector can stay simple and restricted. The dashboard host can be more permissive.
Use this pattern when:
- The collector host has access to file servers, SMB shares, NTFS ACLs, and Active Directory, but has no internet access.
- The collector host cannot install Node, browser tooling, Power BI, or other review tools.
- Raw scan evidence must remain inside a trusted boundary until it is approved for transfer.
- A separate analyst or business-review workstation can open the dashboard package.
ShareSurfer does not change permissions. It reads evidence, writes normalized CSVs, and produces an offline report or dashboard package.
| Host | What it needs | What it creates |
|---|---|---|
| Collector host | Windows PowerShell 5.1, ShareSurfer module, read access to target shares and directory data | Raw CSV export set, scan_manifest.csv, report.html, optional transfer package |
| Dashboard host | Browser and the unpacked ShareSurfer release package | Offline dashboard review folder copied from the export dataset |
The collector host does not need npm, Vite, Playwright, internet access, or a local web server. Release users also do not need Node, npm, Vite, a development server, or internet access on the dashboard host to package and open the standalone dashboard. Download ShareSurfer-0.1.0-pre.43.zip and ShareSurfer-0.1.0-pre.43.zip.sha256 from the ShareSurfer Releases page on an approved connected workstation, verify or record the hash, and move the release package by your approved process. If the checkpoint tag is not visible yet, use the latest published prerelease until v0.1.0-pre.43 appears.
When the release ZIP is extracted to C:\, the ShareSurfer folder is:
C:\ShareSurfer-0.1.0-pre.43\
If Windows Explorer suggests extracting to C:\ShareSurfer-0.1.0-pre.43, change the destination to C:\ to avoid a doubled nested folder. The dashboard host can use the same release folder path, or another local path such as D:\Tools\ShareSurfer-0.1.0-pre.43.
During collection, Invoke-ShareSurferScan prints timestamped phase updates so the operator can tell the scan is still active. Use -Quiet only for scheduled automation. If WinRM/CIM is unavailable, ShareSurfer records the gap as partial share-permission evidence and continues with file/folder evidence where possible. If SMB/RPC is reachable but native security descriptor reads fail, the scan is still partial: review NativeShareSecurityDescriptorUnavailable, NativeShareSecurityDescriptorParseFailed, NativeSecurityDescriptorReadFailed, and NativeSecurityDescriptorParseFailed rows before asking owners to approve the result.
Create a dated export path:
$scanId = 'scan-2026-06-08-finance'
$shareSurferRoot = 'C:\ShareSurfer-0.1.0-pre.43'
$exportPath = "C:\ShareSurfer\exports\$scanId"
$inputRoot = 'C:\ShareSurfer\inputs'
$ownerMappingPath = Join-Path $inputRoot 'owner-mapping.csv'
$ownershipSourcePath = Join-Path $inputRoot 'hr-obs.csv'
$ownershipEnrichmentPath = Join-Path $inputRoot 'ownership-enrichment.csv'
$ownershipDefinitionPath = Join-Path $inputRoot 'ownership-import.definition.json'
$ownershipRerunPath = Join-Path $inputRoot 'ownership-enrichment-rerun.ps1'
$discountedPrincipalPath = Join-Path $inputRoot 'discounted-principals.csv'
Test-Path "$shareSurferRoot\src\ShareSurfer\ShareSurfer.psd1"
Test-Path "$shareSurferRoot\interface\standalone-dashboard\dist\index.html"
Get-ChildItem -Path "$shareSurferRoot\*" -Recurse -File -Include *.ps1,*.psm1,*.psd1 | Unblock-File
New-Item -ItemType Directory -Path $exportPath -Force
New-Item -ItemType Directory -Path $inputRoot -ForceThe Unblock-File line clears the Windows downloaded-file block from ShareSurfer PowerShell files. It is safe to run again after re-extracting or re-copying the release folder.
Both Test-Path commands should return True. If either returns False, confirm the ZIP was extracted to the expected folder before scanning.
Create an owner mapping CSV when you know the expected business owner:
@(
[pscustomobject]@{
Pattern = '\\files01\Finance\*'
Owner = 'Finance Operations'
BusinessUnit = 'Finance'
Source = 'operator'
}
) | Export-Csv -LiteralPath $ownerMappingPath -NoTypeInformation -Encoding UTF8Create a discounted principals CSV when broad HelpDesk, admin, scanner, backup, or platform groups should stay visible but should not drive Migration Discovery relatedness:
@(
[pscustomobject]@{
Identity = 'CONTOSO\HelpDeskOps'
Reason = 'Broad HelpDesk access'
Scope = 'Global'
}
) | Export-Csv -LiteralPath $discountedPrincipalPath -NoTypeInformation -Encoding UTF8Discounted does not mean ignored, safe, approved, or remediated. ShareSurfer still shows the access in the CSVs and report.
If HR, employee, OBS, project, or owner CSVs are available before the scan, normalize them on the collector while it can still read AD. The simplest locked-down pattern is to place the first candidate file at C:\ShareSurfer\inputs\hr-obs.csv; use the full admin ownership import guide when several CSVs need to be selected with the text picker.
if (Test-Path -LiteralPath $ownershipSourcePath) {
Import-Module "$shareSurferRoot\src\ShareSurfer\ShareSurfer.psd1" -Force
Join-ShareSurferOwnershipSources `
-Path $ownershipSourcePath `
-OutputPath $ownershipEnrichmentPath `
-DefinitionPath $ownershipDefinitionPath `
-ObsAttribute 'extensionAttribute10' `
-AdLookupMode Auto `
-ForbiddenOu @('OU=Service Accounts,DC=contoso,DC=com', 'OU=Admins,DC=contoso,DC=com') `
-ReusableCommandPath $ownershipRerunPath `
-Force
}This uses employee ID or employee number values from the CSV to gather matching AD data when directory lookup is allowed, fills available account, mail, title, office, manager, and OBS fields, and writes ownership-enrichment.csv for the scan. The definition JSON and rerun script make the same import repeatable after a refreshed HR/OBS file arrives. If your environment stores OBS outside extensionAttribute10, change -ObsAttribute before running this command.
Import the module:
Import-Module "$shareSurferRoot\src\ShareSurfer\ShareSurfer.psd1" -ForceRun the scan:
$scanParams = @{
TargetPath = '\\files01\Finance'
OutputPath = $exportPath
OperationalPathLengthThreshold = 256
ExplicitAceDepthThreshold = 2
GroupExpansionMaxDepth = 5
ManagerIdentityFormat = 'MailTo'
AdLookupMode = 'Auto'
ObsAttribute = 'extensionAttribute10'
}
if (Test-Path -LiteralPath $ownerMappingPath) {
$scanParams.OwnerMappingPath = $ownerMappingPath
}
if (Test-Path -LiteralPath $ownershipEnrichmentPath) {
$scanParams.OwnershipEnrichmentPath = $ownershipEnrichmentPath
}
if (Test-Path -LiteralPath $discountedPrincipalPath) {
$scanParams.DiscountedPrincipalPath = $discountedPrincipalPath
}
Invoke-ShareSurferScan @scanParamsUse the correct -ObsAttribute for your directory. extensionAttribute10 is the default, but some environments use another attribute such as info.
Do not pass optional input paths unless the files exist. The splatted command above checks for the owner mapping, ownership enrichment, and discounted principals CSVs before adding those parameters, so a first scan can still run without optional inputs.
Optional: record open-file activity before packaging the dataset. This helps reviewers see hot folders that were active during a migration or owner-review window. A one-sample run is good for an ad hoc check:
Invoke-ShareSurferOpenFileAssessment `
-ComputerName 'files01' `
-ShareName 'Finance' `
-OutputPath $exportPath `
-SampleCount 1For longer collection, run the same command from Task Scheduler under the collector account and use a dated $exportPath, or intentionally replace prior open-file assessment files with -Force. The command adds optional open_file_manifest.csv, open_file_samples.csv, open_file_summary.csv, and open_file_errors.csv files. Those files transfer with the rest of the export folder and are imported by the report/dashboard when present.
Validate the export:
$validation = Test-ShareSurferExport -ExportPath $exportPath
$validationGenerate the default offline report on the collector:
ConvertTo-ShareSurferReport -ExportPath $exportPath -OutputPath "$exportPath\report.html"At this point the export folder is the dataset. Keep it together.
Collector handoff checklist:
Test-ShareSurferExportreturnedIsValid=True, or the validation failure is documented before transfer.scan_manifest.csv,evidence_confidence.csv,shares.csv,items.csv,share_permissions.csv,acl_entries.csv,findings.csv,conflicts.csv,collection_errors.csv, andscan_events.csvare present.report.htmlexists in the export folder.evidence_confidence.csvhas no unresolved stop gates for the intended review scope, or the gap is documented before transfer.shares.csvpartial rows andcollection_errors.csvcritical rows have been reviewed by the operator.owner_review_packets.csvandowner_risk_pivots.csvare present when owner mapping was supplied.- Optional
open_file_*.csvfiles are present when open-file activity was collected. - Raw exports are approved for the intended transfer path, or a redacted support bundle will be used instead.
Create a zip package and hash:
$packageRoot = 'C:\ShareSurfer\packages'
if (-not (Test-Path -LiteralPath $packageRoot)) {
Write-Host "Creating missing local handoff package folder: $packageRoot"
New-Item -ItemType Directory -Path $packageRoot -Force | Out-Null
}
$zipPath = Join-Path $packageRoot "$scanId.zip"
if (Test-Path -LiteralPath $zipPath) {
Remove-Item -LiteralPath $zipPath -Force
}
Compress-Archive -LiteralPath (Join-Path $exportPath '*') -DestinationPath $zipPath
Get-FileHash -LiteralPath $zipPath -Algorithm SHA256 |
Export-Csv -LiteralPath "$zipPath.sha256.csv" -NoTypeInformation -Encoding UTF8Move the zip and hash file by your approved transfer process. Examples include an approved file-transfer service, a controlled jump host, removable media governed by policy, or another internal process your organization already trusts.
Do not send raw exports outside the trusted boundary unless your organization has approved that. Raw exports can contain real names, paths, server names, business-unit names, employee identifiers, manager chains, and OBS values.
Unpack the dataset:
$reviewRoot = 'D:\ShareSurfer\reviews\scan-2026-06-08-finance'
New-Item -ItemType Directory -Path $reviewRoot -Force
Expand-Archive -LiteralPath 'D:\Intake\scan-2026-06-08-finance.zip' -DestinationPath $reviewRootConfirm the package hash when your transfer process provides the collector-side hash CSV:
$zipPath = 'D:\Intake\scan-2026-06-08-finance.zip'
$hashCsvPath = 'D:\Intake\scan-2026-06-08-finance.zip.sha256.csv'
$expectedHash = (Import-Csv -LiteralPath $hashCsvPath | Select-Object -First 1).Hash
$actualHash = (Get-FileHash -LiteralPath $zipPath -Algorithm SHA256).Hash
$actualHash -eq $expectedHashThe final line should return True. If it returns False, stop and re-check the transfer before opening or repackaging the dataset.
Open the default report:
Start-Process (Join-Path $reviewRoot 'report.html')Dashboard host received-package checklist:
- The received zip hash matches the hash recorded on the collector side.
- The extracted folder contains
scan_manifest.csvat the top level, not another nested zip or release package folder. report.htmlopens from the extracted review folder.- The ShareSurfer release folder is separate from the scan export folder. The release contains the dashboard template assets; the export folder contains the scan data.
- If the standalone dashboard opens a template/onboarding screen, run
New-ShareSurferStandaloneDashboard.ps1against the extracted export folder and open the generated dashboard output instead.
If you are using the v0.1.0-pre.43 release package, or the latest published prerelease while waiting for the checkpoint tag to appear, the standalone dashboard assets are already built. Package the dataset into a self-contained dashboard folder:
$shareSurferRoot = 'D:\Tools\ShareSurfer-0.1.0-pre.43'
powershell.exe -NoLogo -NoProfile -ExecutionPolicy Bypass -File "$shareSurferRoot\scripts\New-ShareSurferStandaloneDashboard.ps1" `
-ExportPath $reviewRoot `
-OutputPath "$reviewRoot\standalone-dashboard" `
-ForceOpen:
Start-Process "$reviewRoot\standalone-dashboard\index.html"The standalone dashboard folder is static. After packaging, it opens from disk and does not need npm, Vite, a server, or internet access. The release's interface\standalone-dashboard\dist\index.html is only a template shell until you run New-ShareSurferStandaloneDashboard.ps1 against a validated export.
For very large transferred exports, New-ShareSurferStandaloneDashboard.ps1 may stop before writing sharesurfer-data.js and tell you the projected dashboard data is too large for reliable browser review. Check the generated dashboard-manifest.json for the largest dataset contributors. This is a browser safety guardrail, not a collection failure. Use -ForceLargeDashboard only when your review host can tolerate a dashboard that may open slowly or crash.
The legacy report.html is still useful for small and moderate transfers, but it is a single file with embedded data. If ConvertTo-ShareSurferReport refuses a large transferred export with an inline-data guardrail, package the standalone dashboard instead. Use -ForceLargeReport only when the receiving workstation can tolerate one large HTML file that may open slowly or crash.
If browser-based review is still the limiting factor, use the optional native viewer on a Windows review host:
powershell.exe -STA -NoLogo -NoProfile -ExecutionPolicy Bypass -File "$shareSurferRoot\scripts\Start-ShareSurferNativeViewer.ps1" `
-ExportPath $reviewRootThe native viewer reads the transferred CSV files by page and does not use HTML, JavaScript, WebView2, npm, a server, or internet access.
Start with:
owner_review_packets.csvor the dashboard owner review queue.related_data_areas.csvfor migration discovery and like-owned shares/folders.permissioned_groups.csvfor groups that directly grant access.findings.csvfor long paths, broken inheritance, deep explicit ACEs, and service-account candidates.conflicts.csvfor share gate vs file/folder permission mismatches.- Raw evidence tables only when an operator needs the CSV-shaped detail.
For business users, frame the review around who owns the data, why it was flagged, which groups grant access, and what must be resolved before migration planning.
Create a redacted support bundle instead of sending raw exports:
New-ShareSurferSupportBundle `
-ExportPath $exportPath `
-OutputPath 'C:\ShareSurfer\support\scan-2026-06-08-finance-redacted' `
-RedactionMode StableToken `
-RedactionSalt 'case-2026-06-08-finance' `
-IncludeReportValidate and inspect the bundle before sharing it:
Test-ShareSurferExport -ExportPath 'C:\ShareSurfer\support\scan-2026-06-08-finance-redacted'Search for raw domain names, server names, share names, user names, group names, and business-unit names before attaching anything to a ticket.
| Need | Use |
|---|---|
| Strict collector, no extra tooling | Run Invoke-ShareSurferScan, Test-ShareSurferExport, and ConvertTo-ShareSurferReport on the collector. |
| Rich review on another host | Transfer the validated export folder or zip to the dashboard host. |
Dashboard host uses v0.1.0-pre.43 or the latest published prerelease zip |
Run New-ShareSurferStandaloneDashboard.ps1 against the transferred export; no npm or Vite is required. |
| External bug report or support case | Generate a redacted support bundle and inspect it before sharing. |