Validate generated XDR Detection YAML structurally and validate source and converted KQL through official Microsoft Sentinel Triage MCP tools first, with direct API fallback.
75%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./.github/skills/sentinel-xdr-detection-validator/SKILL.mdOffline validation requires contentProvenance.requiredWorkloads records
(workload, dataTypes) and contentProvenance.requiredDataConnectors records
(connectorId, dataTypes). Missing fields, malformed/unknown workloads and
dependencyReviewRequired: true block validation. Use
sentinel-xdr-dependency-helper to review unresolved prerequisites against an
explicitly approved lab. Conversion never calls or requires Log Analytics.
Reviewed empty connector arrays are valid for native XDR-only content.
Live source validation requests Prefer: include-dataSources=true, retains
input metadata, and compares it with authored workload/connector declarations.
It uses API metadata for 1-10 distinct tables; successful missing metadata or
more than 10 tables falls back to the conservative scanner. Failed or partial
queries never become empty successful dependencies. Source connector
declarations are compared without inventing connectors from shared tables.
Authoring can use the helper's explicitly approved lab reads and offline
metadata import without enabling the Qualification-only SDK execution route.
Use the sentinel-xdr-migration CLI for deterministic planning, structural
validation, fallback execution, and reporting. Runtime query execution prefers:
https://sentinel.microsoft.com/mcp/triage.Inspect the connected Triage MCP tools and use a suitable advertised tool first. Do not invent a tool name or assume a capability. Fall back to the corresponding direct provider only when Triage cannot act as a provider, including:
Original Sentinel queries fall back to the Azure Monitor Query SDK (or imported legacy Log Analytics CLI/API results). Advanced Hunting queries fall back to Graph. Do not fall back when Triage successfully executes the request and returns a real KQL semantic/runtime error. That is a detection failure, not an MCP failure. Do not combine providers within one query-family report; if Triage fails mid-batch, rerun that complete batch through its direct provider.
Before any live query, confirm the exact persisted Log Analytics workspace and/or Defender tenant, and verify the required read permissions for that provider. Never choose another workspace to recover from a failure. Do not launch authentication without first asking. Structural validation, runtime execution, schema binding, and qualification are separate outcomes; a provider fallback or successful query never marks a rule validated or proves parity.
For partial publication, do not weaken this rule-level evidence contract.
package-selection-plan counts only unique, current source IDs represented by
eligible deployable Custom Detections against the complete original Sentinel
rule inventory; the partial threshold is strictly over 50%. Qualification may
use only the fresh applied selected subset and must keep excluded item failures
visible. Never relabel a partial selected-query result as full-inventory
Validation or Qualification.
Run sentinel-xdr-migration doctor.
On first run, run sentinel-xdr-migration setup --non-interactive.
Ask before launching interactive authentication. Never block offline conversion.
Run:
sentinel-xdr-migration validate --solution "<solution-path>"Stop if structural errors remain. Each detection requires its own top-level
version (major.minor.patch) in [3.1.0, 4.0.0), separate from
schemaVersion: 1.0.0. Source Sentinel 1.x versions remain valid provenance
and must not be promoted to satisfy this check. For older files without the
XDR version, report the reconversion guidance rather than changing provenance
or accepting Data/solution version fallbacks.
Generate the complete runtime plan:
sentinel-xdr-migration validation-plan --solution "<solution-path>"Use advertised official Triage MCP tools first for every supported
sentinelQuery and advancedHuntingQuery. For Advanced Hunting, invoke
RunAdvancedHuntingQuery. If the connected MCP does not advertise a suitable original Sentinel
workspace-query tool, either run the toolkit's native SDK provider for the
full family or use the legacy Log Analytics CLI/API import path without
treating that capability gap as a KQL failure.
The native source-query runner requires an existing Qualification run and
its locked target. It verifies the active Azure CLI tenant and subscription
without signing in, sends each exact persisted source KQL string directly to
LogsQueryClient.query_workspace(timespan=None), and records full returned
schemas and rows in the ignored run-local SDK report:
sentinel-xdr-migration validate-sentinel-sdk `
--solution "<solution-path>" `
--run-id "<qualification-run-id>"Defaults bound each request to 90 seconds and the complete source family to 30 minutes, with at most two transient retries per query. The complete recursive source inventory must map one-to-one to current generated detections. Authentication, authorization, query, transport and partial result failures are retained distinctly. Zero returned rows indicate query execution only, not parity.
Normalize Advanced Hunting results into a JSON file containing exactly one
entry per detection and the returned target-query output schema array when
custom details are present. Copy querySha256 from the matching
advancedHuntingQuerySha256 in the runtime plan; it must hash the exact KQL
sent to the provider:
{
"results": [
{
"detection": "Example.yaml",
"status": "passed",
"statusCode": 200,
"rowCount": 0,
"querySha256": "<exact advancedHuntingQuery SHA-256 from validation-plan>",
"schema": [{"Name": "DeviceId"}, {"Name": "Timestamp"}],
"error": null
}
]
}Allowed statuses are passed, failed, and blocked. Then record the
provider results:
sentinel-xdr-migration record-runtime-validation `
--solution "<solution-path>" `
--provider triage-mcp `
--results "<normalized-results.json>"If Triage cannot complete an entire query family for a provider-level
reason, create a run-local provider-gap-<family>.json recording the
advertised tool name (or unavailable), exact target reference, one
approved reason code (tool-unavailable, authentication, authorization,
timeout, transient-provider-error, or batch-provider-failure), a
concise reason, batchComplete: true, scopeVerified: true,
permissionsVerified: true, and kqlError: false. Do not use a gap record
for a real KQL error. The CLI rejects incomplete, cross-family, wrong-provider,
or unscoped fallback evidence.
For original Sentinel queries, rerun that complete family against the exact locked workspace. Prefer the native SDK command above; pass the run-local provider-gap evidence if Triage failed:
sentinel-xdr-migration validate-sentinel-sdk `
--solution "<solution-path>" `
--run-id "<qualification-run-id>" `
--provider-gap-evidence "<run-local-provider-gap-sentinel.json>"For externally imported provider results, normalize one result per
detection and include querySha256 from that rule's
sentinelQuerySha256 plan entry, then record it with the gap evidence:
sentinel-xdr-migration record-runtime-validation `
--solution "<solution-path>" `
--provider log-analytics-cli `
--results "<complete-sentinel-results.json>" `
--provider-gap-evidence "<run-local-provider-gap-sentinel.json>"If and only if Triage has an Advanced Hunting provider-level failure, run the complete Advanced Hunting batch through Graph with the same kind of run-local evidence:
sentinel-xdr-migration validate-advanced-hunting `
--solution "<solution-path>" `
--provider-gap-evidence "<run-local-provider-gap-advanced-hunting.json>"Runtime providers create JSON and self-contained HTML reports under
Solutions\<solution>\Logs\sentinel-xdr-migration\<run-id>. Treat blocked as an
environment gap, not a conversion failure.
For every rule:
sentinelQuery;advancedHuntingQuery;passed Sentinel results without a matching querySha256 are
blocked. Graph results bind automatically to the exact Advanced Hunting
query executed by the validator. A query rewrite invalidates old evidence;
rerun the complete Sentinel and Advanced Hunting families for the current
artifact before the workflow can pass runtime validation.Zero rows are not proof of behavioral parity. Record them as execution success with data validation still pending. A table probe that executes and returns zero rows proves the table binds on that query surface.
Do not change contentProvenance.conversion.status to validated unless
both queries execute and the entity output has been reviewed.
Defender Advanced Hunting and Sentinel Log Analytics are separate query surfaces even when the Defender portal shows a selected Sentinel workspace. A table name resolving in Advanced Hunting does not prove that the same name resolves through the Log Analytics workspace API, and vice versa.
sentinelQuery only against the exact persisted
Log Analytics workspace.advancedHuntingQuery only through Defender Advanced
Hunting.IdentityInfo unavailable through log-analytics-workspace; available through defender-advanced-hunting.For an Authoring profile, an environment-only runtime block does not prevent
V3.1 packaging when structural validation passed. Complete validation as passed
with runtimeStatus=environment-blocked only when no current exact-query
KQL/runtime failure exists, preserve the provider error and query surface, and
do not claim the detection is runtime-qualified. For a
Qualification profile, the same runtime block remains blocking until the
selected lab environment satisfies the required query surfaces.
Return a per-rule result and an overall pass/needs-review summary.
Best-effort entity-mapping assumptions recorded by conversion do not prevent read-only Sentinel/Advanced Hunting execution or output-schema binding tests. Run and report those tests against the exact hash-bound queries, retaining the assumption as pending human review. A successful query or custom-detail schema binding is not approval, entity correlation, or alert parity. Keep technical failures and other unresolved review findings blocking as applicable; do not package or deploy while an entity-mapping review remains pending.
For unresolved table/schema or conversion assumptions, use provider-owned
evidence: standard-table and schema documentation, live query schema from the
selected provider, or the custom connector's DCR/table metadata. Do not
substitute customer research or invent a schema. Present each proposed
assumption with its exact scope, source/query hash, evidence, and accept or
reject choice; no decision is automatic. Accepted assumptions still require
reconversion and the normal structural/runtime checks. If content hashes change,
re-review rather than reusing an earlier decision.
Azure/Azure-Sentinel
2985095
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.