Skip to content

feat: an MDE exclusion reviewer and a PowerShell author - #1

Merged
craigthackerx merged 3 commits into
mainfrom
feat/defender-and-powershell-agents
Aug 24, 2026
Merged

feat: an MDE exclusion reviewer and a PowerShell author#1
craigthackerx merged 3 commits into
mainfrom
feat/defender-and-powershell-agents

Conversation

@craigthackerx

Copy link
Copy Markdown
Contributor

Two new agents on the existing pattern, plus the token work that makes the PowerShell one rebrand cleanly.

mde-exclusion-reviewer

Reviews Defender for Endpoint and Defender Antivirus exclusion requests, and audits exclusion lists that already exist. It is a reviewer, not an operator: it never applies anything, and the manifest disclaimer says a named human owns the decision.

One verdict per answer, as the first line: APPROVE, NARROW, REJECT, or INSUFFICIENT EVIDENCE.

The nine safety nets:

1 The never-exclude lists are absolute, and a match is a rejection with the entry quoted
2 State the blast radius every time - a process exclusion also stops network protection and ASR rules inspecting that process
3 Narrowest form wins: contextual, then full path, then folder, then wildcard
4 Fully qualified paths, never a bare file name
5 Environment variables resolve as LocalSystem, so %TEMP% is C:\Windows\TEMP
6 Check redundancy against automatic Windows Server role exclusions
7 One list per workload; IIS and SQL Server do not share one
8 Evidence, not anticipation
9 An owner and a review date, even on an approval

Safety net 2 is the one worth the agent existing for. The requester almost never knows that excluding a process silently disables ASR enforcement for it.

The never-exclude lists are uploaded knowledge, not left to web search, because scoped search only reads what Bing indexes and a reviewer that cannot see the authoritative list is a reviewer with an opinion.

powershell-author

House style plus enterprise PowerShell 7. Approved verbs and the noun prefix, Set-StrictMode -Version Latest, typed and validated parameters, SupportsShouldProcess actually gated on ShouldProcess, comment-based help, objects rather than Write-Host, structured logging with the canonical TRACE to FATAL vocabulary and OTel severity numbers, terminating versus non-terminating errors, secrets, and the PSScriptAnalyzer and Pester gates.

Rebranding, which was the explicit ask

The PowerShell conventions would have been hardcoded branding, so they are tokens: cmdlet_prefix and ps_module_name. Neither adds a prompt, because new-profile derives both from the organisation name (ACMEAcme, AcmeAcmeHelpers).

Proven end to end against a throwaway profile:

Invoke-AcmeTerraformPlan   OK
Write-AcmeLog              OK
AcmeHelpers                OK
ACME_LOG_LEVEL             OK
Ldo/LibreDevOps leakage:   False

Budgets and gates

Agent Instructions
mde-exclusion-reviewer 7593/8000 (94%)
powershell-author 7264/8000 (90%)

Both under the 7600 warning line, so the next edit does not fail the build. just validate clean: render drift gate plus lint, 5 agents, 0 warnings.

Six knowledge packs added. The Defender ones come from the public MicrosoftDocs/defender-docs mirror, so they are refreshable with just update-knowledge like everything else.

Also de-hardcoded the agent count in three docs that still said "both agents" or "three agents".

Two agents, on the existing pattern: fragments composed at build time,
branding in the profile, knowledge fetched and committed.

mde-exclusion-reviewer reviews Defender for Endpoint and Defender
Antivirus exclusion requests and audits lists that already exist. It is a
reviewer, not an operator, and the manifest says so: a named human owns
every exclusion decision.

Nine safety nets, applied to every request. The never-exclude folder,
extension and process lists are uploaded as knowledge rather than left
to web search, because a reviewer that cannot see the authoritative list
is a reviewer with an opinion, and a match is a rejection with the entry
quoted. It states the blast radius every time, in particular that a
process exclusion also stops network protection and ASR rules inspecting
that process, which is the least understood consequence in the feature.
Then narrowest form wins, fully qualified paths, LocalSystem variable
resolution, redundancy against automatic server-role exclusions, one
list per workload, evidence rather than anticipation, and an owner and
review date even on an approval. One verdict per answer: APPROVE,
NARROW, REJECT or INSUFFICIENT EVIDENCE.

powershell-author answers house style and enterprise PowerShell 7:
approved verbs and the noun prefix, strict mode, typed and validated
parameters, comment-based help, objects rather than host writes,
structured logging with the canonical level vocabulary, terminating
versus non-terminating errors, secrets, and the analyzer and Pester
gates.

Two new profile tokens carry the PowerShell conventions so they rebrand
with everything else: cmdlet_prefix and ps_module_name. Neither is a new
question, because new-profile derives both from the organisation name.
Proven end to end: rendered under a throwaway ACME profile the agent
emits Invoke-AcmeTerraformPlan, Write-AcmeLog, AcmeHelpers and
ACME_LOG_LEVEL with no Ldo or LibreDevOps leakage, and lint is clean.

Six knowledge packs added, the Defender ones from the public
MicrosoftDocs/defender-docs mirror. Budgets: exclusion reviewer
7593/8000, PowerShell author 7264/8000, both under the 95 percent
warning line. Also de-hardcoded the agent count in three docs that said
"both" or "three".
The language is shared between the two products and the schemas are not,
which is the failure this agent exists to prevent: a hunt written
against the wrong table set does not error helpfully, it returns nothing,
and an empty result looks identical to a clean environment. So the agent
names the target before it writes and asks when the request does not say.

It also separates two artefacts people conflate. A hunt explores and may
be noisy on purpose; a detection runs unattended and pages someone. It
says which it is writing and refuses to hand over an untuned hunt as a
rule, listing what still has to happen: tuning, entity mapping, severity,
ATT&CK.

The correctness section carries the traps that pass review and then
mislead an investigation. First among them, verified against the Kusto
reference: join defaults to kind=innerunique, which deduplicates the LEFT
side, so rows disappear silently. The join operator page is a knowledge
pack of its own for that reason. Then case sensitivity, has versus
contains as terms versus substrings, per-table timestamp columns, and
arg_max for the latest record.

Performance is stated in the order the engine cares about rather than as
a list of tips: datetime predicate first because Kusto indexes it and
eliminates whole shards unread, then term-level string predicates most
selective first, then the cheaper operator of each pair, never search *,
smaller table on the left of a join, project early, materialize a reused
let, limit anything exploratory.

Seven knowledge packs, the Kusto ones from the public
MicrosoftDocs/dataexplorer-docs mirror and the hunting ones from
MicrosoftDocs/defender-docs. Budget 7520/8000, under the warning line.
The sibling to the hunt author, and the reason it carries the whole
platform rather than just the rule form: most rule problems are really
problems with the link either side of it. A rule that fires constantly is
usually grouping or threshold, not the query. A rule nobody can
investigate is usually a missing entity mapping. A rule that misses
events is usually a schedule that does not match the source's ingestion
delay.

So the purpose fragment carries the pipeline: connectors ingest into
tables, rules run KQL and raise alerts, alerts become incidents, entities
correlate them and are what an analyst pivots on, automation rules fire
on incident or alert events and call playbooks, watchlists hold reference
data, UEBA adds baselines.

Two platform facts that change answers are stated up front: Sentinel is
Defender-portal only after 31 March 2027, and on a Defender-onboarded
workspace Defender XDR creates and names incidents, the Microsoft
Security rule type is auto-disabled and reopening closed incidents is
unavailable. Prefer an ASIM parser over a native table so a rule survives
a change of data source.

Every limit is quoted rather than approximated, each verified against the
reference: query 1 to 10,000 characters with search * and union *
rejected outright, schedule 5 minutes to 14 days with interval no longer
than lookback, the 5 minute scheduled delay against NRT's 2 minutes on
ingestion time, 10 entity mappings of 3 identifiers with at least one
required, 500 entities per alert divided equally across mappings and a
64 KB field cap, 150 alert caps on both event grouping and alert
grouping, suppression up to 24 hours.

A rule with no entity mapping is treated as a defect rather than a
preference, because it produces an incident nobody can pivot from.

Nine Sentinel knowledge packs plus the Kusto best practices, since a rule
query runs on a schedule and its cost is recurring. Sentinel docs now
live in the defender-docs mirror rather than azure-docs, which is its own
signal. Budget 7596/8000.
@craigthackerx
craigthackerx merged commit e1f172e into main Aug 24, 2026
3 checks passed
@craigthackerx
craigthackerx deleted the feat/defender-and-powershell-agents branch August 24, 2026 21:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant