Overview
This lab uses Microsoft’s GigaWiper research as a case study for the July 2026 preview of Defender XDR custom detection rules as code. It includes five rule definitions, a disabled deployment canary, GitHub validation, hunting queries, synthetic KQL fixtures, a bounded Windows telemetry generator, and a manual Graph-only fallback after the native preview path returned the result observed July 11β12, 2026.
Blog post: GigaWiper Detection as Code: Testing the Sentinel Repositories Preview
Companion repository: j-dahl7/gigawiper-detection-as-code
Safety boundary
The lab does not download malware, wipe disks, encrypt files, delete boot files, disable recovery, or clear operational Windows logs. Boot/recovery behavior is validated only with synthetic KQL rows.
What the pack defines
| ID | Detection | Desired state | Evidence path |
|---|---|---|---|
nls-gw-000-canary | Deployment canary | Disabled | Exact-ID API read-back |
nls-gw-001-onedrive-persistence | OneDrive-lookalike task and registry persistence | Enabled | Current query re-matched live telemetry; the separate scheduled portal alert used the validation revision |
nls-gw-002-recovery-boot-tampering | Recovery and boot tampering | Enabled | Synthetic only |
nls-gw-003-event-log-destruction | Windows event-log clearing | Enabled | Observed benign custom-log telemetry plus a separate portal-native scheduled alert |
nls-gw-004-minio-transfer-staging | Unusual MinIO client staging | Enabled | Filename-only telemetry plus a separate portal-native NRT alert |
nls-gw-005-candy-rename-burst | .candy rename burst | Enabled | Current optimized query matched live telemetry; no saved portal rule or alert |
The six retained exact IDs were read back in the validation revision’s desired
state through the bounded Graph fallback. The disabled canary and five enabled
behavior rules had zero current automatedActions and zero deprecated
responseActions. Alert evidence below belongs only to three separately
created portal-native validation rules.
Revision boundary: the current NLS-GW-001 post-correlation deduplication and optimized NLS-GW-005 time-window join were independently re-run read-only against retained live telemetry. Neither current revision was applied to the six retained Graph objects or the portal-native validation rules, and no new alert is attributed to either revision.
Quick start
Plan for 90β150 minutes of hands-on work. If this is the first subscription in
the tenant to activate Defender for Endpoint through Defender for Cloud, allow
up to 12 hours for service activation, followed by possible telemetry-ingestion
delay. Do not generate validation telemetry until the machine API reports the
endpoint Onboarded and Active and Advanced Hunting returns DeviceInfo.
git clone https://github.com/j-dahl7/gigawiper-detection-as-code.git
cd gigawiper-detection-as-code
./scripts/Test-Lab.ps1
The validation workflow compiles all six templates and checks the stable-ID, single-tactic, query-column, fixture, endpoint, fallback, and safety contracts.
In a dedicated lab tenant, you can connect the repository through Microsoft
Sentinel > Content management > Repositories and select Custom Detection
Rules to examine the native preview path. In the July 11β12 validation window,
that generated path failed all six corrected templates with outer
InvalidTemplateDeployment and inner ProviderError: Encountered internal server error. Because the root cause remains unconfirmed, broader role
assignments are not a validated workaround.
If you intentionally use the temporary fallback, first follow
docs/GRAPH-FALLBACK.md
to create your own dedicated Entra application, GitHub OIDC credential, and
environment. The identity must have only the Microsoft Graph application
permission CustomDetection.ReadWrite.All and no Azure RBAC assignment. Then
manually run Deploy custom detections - preview fallback from main, enter
the exact confirmation DEPLOY_PREVIEW_FALLBACK, deploy the disabled canary
first, and select All only after its exact-ID read-back succeeds. Do not run
the fallback concurrently with a working native synchronization path.
Run safe telemetry only from an elevated session on a disposable MDE endpoint:
./scripts/Invoke-SafeGigaWiperTelemetry.ps1
Cleanup
./scripts/Invoke-SafeGigaWiperTelemetry.ps1 -CleanupOnly
Then complete the control-plane cleanup:
- Remove the Sentinel Repository connection, then verify that its
connection-created managed identity and Microsoft Sentinel Contributor,
Logic App Contributor,
CustomDetection.ReadWrite.All, and branch-scoped GitHub OIDC grants are retired. Deselecting Custom Detection Rules only stops that content type and is not identity cleanup. - Delete only the six exact
nls-gw-*custom detection IDs through Defender XDR or a separately authorized Graph operation. The fallback has no delete or prune mode. - Separately delete portal rules
NLS-GW-LIVE-001,NLS-GW-LIVE-003, andNLS-GW-LIVE-004; there is no LIVE-005 object. - Delete the dedicated fallback app registration and GitHub environment variables after rule cleanup.
- Delete the remaining credential-less
nls-gigawiper-validation-20260711diagnostic app registration and its tenant-wide Graph grants. - Delete only the dedicated disposable Azure resource group used for endpoint validation.
Current validation status
Live tenant validation ran July 11β12, 2026; repository hardening and CI were revalidated July 13:
- The Bicep pack, endpoint template, five positive plus five negative exact-query fixture contracts, fallback controls, and safety tests pass locally. The separate read-only synthetic runner passed all ten rows through Advanced Hunting.
- The native Repository connection targets
main, uses theCustomDetectioncontent type, and generated its expected OIDC workflow. Its identity held the documented Graph permission and could read a rule by exact ID. - The connection-generated native workflow and helper are retained outside
.github/workflowsas non-reusable evidence artifacts. They cannot run from the public repository. A native retest requires a new Repository connection, review of its freshly generated files, and a deliberate ownership transfer away from the Graph fallback. - Native synchronization returned outer
InvalidTemplateDeploymentand innerProviderErrorfor all six corrected templates. That non-specific native-path response is distinct from the earlier GraphInvalidInput - Only one tactic is currently supportedcontract error, which was corrected and added to CI. - Manual Graph-only GitHub OIDC fallback run
29180593038succeeded. All six validation-revision IDs returned HTTP 200 and passed semantic read-back: five rules enabled, the canary disabled, and zero response actions on every rule. The later current NLS-GW-001 and NLS-GW-005 revisions were not applied to those retained objects. - The fallback identity has only
CustomDetection.ReadWrite.All, no stored secret, and zero Azure RBAC assignments. The workflow operates only on the exact six IDs, uses GET plus POST or PATCH, and has no delete or prune path. - The disposable endpoint has default inbound deny and no custom inbound NSG
rules. The Defender machine API reports it
OnboardedandActive, and Advanced Hunting receivesDeviceInfo. - The four bounded telemetry jobs exited successfully. The exact checked-in KQL
produced live benign matches for NLS-GW-001, NLS-GW-003, NLS-GW-004, and
NLS-GW-005. Seven inert
.candyrename rows satisfied the burst query after an ingestion delay. NLS-GW-002 remains synthetic-only by design. - Three separately created portal-native rulesβ
NLS-GW-LIVE-001,NLS-GW-LIVE-003, andNLS-GW-LIVE-004βgenerated three Custom detection / Microsoft Defender for Endpoint alerts onnls-gw-lab. Incident628is High with Active alerts 3/3, and all three alert pages record that no response actions were taken. - LIVE-001 and LIVE-003 alerted during their initial scheduled evaluation over prior benign telemetry. The LIVE-004 NRT alert incorporated a post-rule safe marker as its last activity; the evidence does not establish that marker as the alert’s sole cause.
- NLS-GW-005 matched live telemetry, but repeated portal wizards stopped at
Supported entities could not be loaded; no 005 portal rule or alert exists or is claimed. NLS-GW-002 remains synthetic-only. - A separate built-in Defender alert,
System executable renamed and launched, remains outside the three custom-alert claim.
The companion article’s evidence set includes the native-failure capture, Graph
fallback and scheduler output, Advanced Hunting results, the LIVE-004
no-actions page, a historical one-alert incident view, and a tightly cropped
final incident 628 Alerts tab. The final capture shows the High, Active incident
with exactly LIVE-004, LIVE-003, and LIVE-001 on nls-gw-lab. The crop removes
the global portal header and account or tenant identifiers while preserving the
incident and alert rows. Before the LIVE rules were created, an exact NLS-GW
filter returned zero rows despite successful Graph read-back. A follow-up
filter now returns exactly the three LIVE rules and still none of the six
Graph-fallback objects. Their portal visibility remains a separate open
validation item; the cause is unconfirmed, and no alert attribution is assigned
to those objects. Native Repository synchronization remains recorded in its
observed Failed state.
