Files
AutopilotMonitor/rules/dist/gather-rules.json
T
Oliver Kieselbach 33618e183d feat(wu-oobe): detect & surface Windows Update during OOBE + self-maintaining rule sunset
Windows Update activity during Autopilot OOBE/ESP is a blind spot no other tool
(Intune console included) surfaces well — a cumulative update installing mid-OOBE
can break enrollment (r/Intune KB5095189). This makes it visible with secured
evidence.

Agent (net48):
- WindowsUpdateTracker + WindowsUpdateWatcherHost: watch
  Microsoft-Windows-WindowsUpdateClient/Operational (EventIDs 19/20/43/44 =
  success/failure/install-started/download-started), startup backfill (OOBE updates
  run before the agent starts), RecordId watermark dedup (restart boundary vs
  intra-run seen-set so a high-id live event can't hide older backfill events),
  HRESULT->symbol decode. Emits windows_update_succeeded/_failed/_started with the
  real event Timestamp. Default-on config knobs; uncertain EventIDs configurable
  without redeploy.
- RegistryCollector: emitOnlyIfExists (suppress positive-assertion events when the
  key is absent) + Registry64 base view by default (bitness-independent, matches
  TenantIdResolver) with optional registryView override.

Rules:
- ANALYZE-DEV-004 (high: WU failed during enrollment, high-insight not KO) +
  ANALYZE-DEV-005 (info: WU installed). reboot_pending corroboration matches
  event_data exists==true.
- GATHER-DEVICE-005 -> windows_update_reboot_pending (emitOnlyIfExists),
  GATHER-DEVICE-004 -> windows_update_history (Get-HotFix, opt-in).
- 5 EventTypes synced across Constants + MCP resource-catalog + web eventTypes.

Self-maintaining rule lifecycle (analyze + gather parity):
- Gather rules gain the sunset/orphan-GC that only analyze had
  (ProcessSunsetGatherRuleAsync + runtime filter + seed/reseed/github paths).
- RuleProvenance field (embedded/github, null=embedded back-compat): the embedded
  catalog only sunsets its own rules; GitHub-reseeded rules ahead of the deployed
  binary (new ids AND content updates to existing ids) are exempt and reclaimed to
  embedded once the binary catches up. No orphans, no operator knowledge required.

Verified: full solution builds; backend suite 2770 pass, agent suite 1638 pass;
rules AJV-valid + combined.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 18:22:41 +02:00

221 lines
8.4 KiB
JSON
Generated

{
"$schema": "../schema/gather-rule.schema.json",
"rules": [
{
"ruleId": "GATHER-APPS-001",
"title": "IME Logs directory check",
"description": "Checks whether the Intune Management Extension log directory exists and reports file sizes. Useful to verify IME is active and logs are being written.",
"category": "apps",
"version": "1.0.0",
"author": "Autopilot Monitor",
"enabled": false,
"collectorType": "file",
"target": "C:\\ProgramData\\Microsoft\\IntuneManagementExtension\\Logs",
"trigger": "startup",
"outputEventType": "gather_ime_logs_directory",
"outputSeverity": "Info",
"tags": [
"apps",
"ime",
"logs"
]
},
{
"ruleId": "GATHER-DEVICE-001",
"title": "Collect dsregcmd join status",
"description": "Runs dsregcmd /status to capture the Azure AD / Entra join state when the device enters the Account Setup phase.",
"category": "device",
"version": "1.0.1",
"author": "Autopilot Monitor",
"enabled": false,
"collectorType": "command_allowlisted",
"target": "dsregcmd /status",
"trigger": "phase_change",
"triggerPhase": "AccountSetup",
"outputEventType": "gather_dsregcmd_status",
"outputSeverity": "Info",
"tags": [
"device",
"entra",
"join"
]
},
{
"ruleId": "GATHER-DEVICE-002",
"title": "Collect last system startup event",
"description": "Collects the most recent Event ID 12 (Kernel-General) from the System log which indicates the last OS startup time.",
"category": "device",
"version": "1.0.0",
"author": "Autopilot Monitor",
"enabled": false,
"collectorType": "eventlog",
"target": "System",
"parameters": {
"eventId": "12",
"source": "Microsoft-Windows-Kernel-General",
"maxEntries": "1"
},
"trigger": "startup",
"outputEventType": "gather_last_startup_event",
"outputSeverity": "Info",
"tags": [
"device",
"startup",
"boot"
]
},
{
"ruleId": "GATHER-DEVICE-003",
"title": "BIOS information",
"description": "Queries WMI for BIOS details including manufacturer, version, serial number, and release date. Helps correlate firmware-level issues with enrollment problems.",
"category": "device",
"version": "1.0.0",
"author": "Autopilot Monitor",
"enabled": false,
"collectorType": "wmi",
"target": "SELECT * FROM Win32_BIOS",
"trigger": "startup",
"outputEventType": "gather_bios_info",
"outputSeverity": "Info",
"tags": [
"device",
"bios",
"hardware"
]
},
{
"ruleId": "GATHER-DEVICE-004",
"title": "Windows Update history snapshot",
"description": "Lists recently installed hotfixes/updates (Get-HotFix) at agent startup as secondary corroboration of updates applied during enrollment. Complements the live WindowsUpdate watcher — catches updates whose events fell outside the watcher's backfill window. Opt-in: Get-HotFix spawns a PowerShell cmdlet and only reports QFE-registered updates (it misses some cumulative/driver updates and all failures), so enable per tenant after weighing the OOBE cost.",
"category": "device",
"version": "1.1.0",
"author": "Autopilot Monitor",
"enabled": false,
"collectorType": "command_allowlisted",
"target": "Get-HotFix | Select-Object -First 10 HotFixID, InstalledOn, Description",
"trigger": "startup",
"outputEventType": "windows_update_history",
"outputSeverity": "Info",
"tags": [
"device",
"windows-update",
"hotfix",
"oobe"
]
},
{
"ruleId": "GATHER-DEVICE-005",
"title": "Windows Update pending reboot",
"description": "Checks the Component Based Servicing RebootPending registry key at agent startup and emits windows_update_reboot_pending ONLY when a reboot is actually pending (the key exists). A pending reboot present when the agent starts is a high-confidence corroborator that a Windows Update (often a quality/cumulative update installed during the OOBE 'Getting updates' phase, before the agent started) landed and now needs a restart — which can delay or block enrollment completion.",
"category": "device",
"version": "1.2.0",
"author": "Autopilot Monitor",
"enabled": true,
"collectorType": "registry",
"target": "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Component Based Servicing\\RebootPending",
"parameters": {
"emitOnlyIfExists": "true",
"severityIfExists": "Warning"
},
"trigger": "startup",
"outputEventType": "windows_update_reboot_pending",
"outputSeverity": "Info",
"tags": [
"device",
"windows-update",
"reboot",
"servicing",
"oobe"
]
},
{
"ruleId": "GATHER-ENROLL-001",
"title": "MDM enrollment diagnostic events",
"description": "Collects recent events from the DeviceManagement Enterprise Diagnostics Provider at the FinalizingSetup phase. Captures MDM sync errors, policy application failures, and enrollment diagnostics accumulated throughout the session.",
"category": "enrollment",
"version": "1.0.0",
"author": "Autopilot Monitor",
"enabled": false,
"collectorType": "eventlog",
"target": "Microsoft-Windows-DeviceManagement-Enterprise-Diagnostics-Provider/Admin",
"parameters": {
"maxEntries": "10"
},
"trigger": "phase_change",
"triggerPhase": "FinalizingSetup",
"outputEventType": "gather_mdm_enrollment_events",
"outputSeverity": "Info",
"tags": [
"enrollment",
"mdm",
"diagnostics"
]
},
{
"ruleId": "GATHER-ENROLL-002",
"title": "Applied MDM device policies",
"description": "Reads the PolicyManager registry key to list all MDM device policies that have been applied. Verifies that expected compliance and configuration policies landed on the device during enrollment.",
"category": "enrollment",
"version": "1.0.0",
"author": "Autopilot Monitor",
"enabled": false,
"collectorType": "registry",
"target": "HKLM\\SOFTWARE\\Microsoft\\PolicyManager\\current\\device",
"parameters": {
"listSubkeys": "true"
},
"trigger": "phase_change",
"triggerPhase": "FinalizingSetup",
"outputEventType": "gather_mdm_device_policies",
"outputSeverity": "Info",
"tags": [
"enrollment",
"mdm",
"policies",
"compliance"
]
},
{
"ruleId": "GATHER-ID-001",
"title": "Machine certificates",
"description": "Lists certificates in the local machine personal store (My). Verifies that the MDM enrollment certificate and any SCEP certificates have been provisioned.",
"category": "identity",
"version": "1.0.0",
"author": "Autopilot Monitor",
"enabled": false,
"collectorType": "command_allowlisted",
"target": "certutil -store My",
"trigger": "startup",
"outputEventType": "gather_machine_certificates",
"outputSeverity": "Info",
"tags": [
"identity",
"certificates",
"scep"
]
},
{
"ruleId": "GATHER-ID-002",
"title": "Machine certificate store (PowerShell)",
"description": "Enumerates certificates in the local machine personal store (Cert:\\LocalMachine\\My) using PowerShell. Returns structured JSON with subject, thumbprint, issuer, and validity dates for each certificate. Useful for verifying MDM enrollment certificates, SCEP certificates, and any other machine certificates provisioned during Autopilot enrollment.",
"category": "identity",
"version": "1.0.0",
"author": "Community",
"isCommunity": true,
"enabled": true,
"collectorType": "command_allowlisted",
"target": "$c = Get-ChildItem Cert:\\LocalMachine\\My; if ($c) { $c | Select-Object Subject, Thumbprint, Issuer, NotBefore, NotAfter, HasPrivateKey | ConvertTo-Json } else { '{\"CertificateCount\": 0}' }",
"trigger": "phase_change",
"triggerPhase": "FinalizingSetup",
"outputEventType": "gather_machine_cert_store",
"outputSeverity": "Info",
"tags": [
"identity",
"certificates",
"machine-store",
"powershell"
]
}
]
}