CASE-2026-0311-A · 2026-03-11 Initial: Critical Corrected: Benign DEEP SELF-CORRECTION

The agent built an APT28 attribution.
Then it caught itself.

Nine “unfamiliar sign-in” alerts triggered a 30-day lookback. The investigator concluded a sustained nation-state campaign with high confidence. The senior reviewer then found that the lookback had dropped a single filter, and every “APT detection” feeding the conclusion had already been resolved as benign by the source platform.

What fired
9 “Unfamiliar sign-in properties” alerts from Azure AD Identity Protection across 3 offices in 24 hours.
First-pass verdict
Critical Threat: APT28 / YTTRIUM campaign, 30+ days. Confidence: HIGH. Disposition: RECOMMEND ESCALATION.
Corrected verdict
Standard: 9 identity alerts remain actionable. APT attribution withdrawn. ~53 “APT detections” already resolved/benign by source platform.
14
FSQL queries
8m
Workers time
6
Mesh sources
~600
Records analyzed
9
Hosts in scope
$3.6-7.2K
Analyst cost saved
→ Agents recommend. Humans decide.

The first-pass agent published a confident, high-severity APT attribution. The senior reviewer caught the methodology error and reversed the verdict. The analyst sees both passes and the evidence that moved the call.

→ Findings stress-tested, not just summarized.

The reviewer did not synthesize. It interrogated. It re-ran the load-bearing queries with corrected predicates. Severity moved down here. It moved up on the ContentServer C2 case. Both directions are part of the contract.

→ Audit trail catches methodology errors.

The reviewer didn’t just re-evaluate the conclusion. It re-ran the queries with corrected predicates. The error was in the query, not the reasoning.

Initial Signal

Nine users. Three offices. Twenty-four hours.

At 18:16 UTC on 2026-03-10, Azure AD Identity Protection raised “Unfamiliar sign-in properties” against katherine.p*** on host DC-1659. Inside twenty-four hours, eight more identical alerts followed: nicole.m***, brian.c***, emma.s***, anna.b***, ronald.b***, kenneth.b***, matthew.s***, and steven.n***, spanning hosts in Bangalore (BD), Washington (DC), and New York (NY).

Nine distinct users. Three offices. All inside the same /24 subnet. All within a single working day. The cluster pattern is what an investigator notices first, and what the agent flagged for DEEP-tier investigation.

First Read

A 30-day lookback built an APT28 case.

The investigator escalated to DEEP tier on multi-signal pattern and ran a 30-day historical lookback against the four most recent hosts. The lookback surfaced Dukozy-labeled malware. Seadask-labeled malware. YTTRIUM actor activity. Bladabindi backdoor. Persistence mechanisms: AppCertDlls, IFEO, WMI, scheduled tasks, masqueraded services. Internal port-scanning from a host outside the affected subnet. PowerShell policy bypasses.

The story wrote itself: a sustained, multi-week intrusion by a nation-state actor. Approximately 600 detection records across four hosts. ~53 specifically labeled with APT28 / YTTRIUM family signatures. The agent published a Critical Threat verdict with HIGH confidence and recommended immediate incident response: network isolation, credential reset, forensic imaging.

First-pass disposition Critical Threat
RECOMMEND ESCALATION · APT28 (YTTRIUM) Multi-Host Compromise
Confidence: HIGH Severity: 9.2 / 10 Tier: DEEP Records: ~600

This is where most autonomous investigators stop: confident answer, polished narrative, ready to ship.

Hypotheses Tested

Four working theories, all consistent with APT.

The investigator tested each hypothesis against the 30-day record set. All four corroborated the APT28 attribution. None was disconfirmed.

H1 · TARGETED CAMPAIGN
The breadth of compromise indicates a targeted operation, not opportunistic infection.
Supporting: 9 hosts across 3 offices in 24h; same /24 subnet; multi-user pattern. Tested against: commodity ransomware patterns (single-host, broad-IP). No match.
H2 · APT28 ATTRIBUTION
Malware family labels and actor-activity detections attribute to APT28 / YTTRIUM.
Supporting: Microsoft Defender labeled detections as Dukozy, Seadask, “YTTRIUM Actor”, “YTTRIUM malicious file.” Bladabindi commonly used by APT28 for initial access. Tested against: commodity malware re-use; partial overlap with criminal actors noted but consistent with APT tradecraft.
H3 · LONG-DWELL PERSISTENCE
7+ persistence mechanisms per host indicate intent for sustained access.
Supporting: AppCertDlls, IFEO, WMI subscriptions, scheduled tasks, masqueraded services, logon scripts, registry run keys observed across the 4 hosts. Tested against: admin tooling baseline. Patterns do not match.
H4 · LATERAL MOVEMENT PIVOT
10.100.21.239 conducting internal scanning indicates a pivot host.
Supporting: Recurring port-scan events against the 172.16.16.x subnet, originating from a different subnet. Tested against: authorized scanner inventory. Host not registered in CrowdStrike or Google Workspace Directory.

Four hypotheses tested, all corroborated. The investigator finalized the report and handed it to the senior reviewer for sign-off.

Reviewer’s Challenge

One missing filter. The verdict collapses.

The senior reviewer’s first move was not to read the conclusion. It was to read the queries. Specifically Q5 through Q8: the 30-day per-host lookbacks that surfaced Dukozy, Seadask, YTTRIUM, Bladabindi, persistence mechanisms, and ~600 detection records.

The reviewer noticed that the Gate 1 intake query filtered correctly on status_id = NEW. The Gate 2 enrichment queries did not.

The methodology error · side-by-side

Q5 as executed, 30-day lookback (BD-2578)

QUERY detection_finding.message, detection_finding.time, detection_finding.severity_id WITH detection_finding.evidences.dst_endpoint.ip = ‘172.16.16.60’ // status_id filter dropped AFTER 30d → 39 records (treated as active)

Q5 corrected, what should have run

QUERY detection_finding.message, detection_finding.time, detection_finding.severity_id, detection_finding.status_id WITH detection_finding.evidences.dst_endpoint.ip = ‘172.16.16.60’ AND detection_finding.status_id = NEW AFTER 30d → 5 records (1 identity + 4 behavioral)
The same query, with the filter the intake stage already used. Every Dukozy, Seadask, YTTRIUM, and Bladabindi detection in the original 39-record result set had a status_id of RESOLVED with status_detail = "Benign", meaning Microsoft Defender had already investigated and dispositioned each one as a false positive. The investigator built an APT28 narrative on top of vendor-resolved benign alerts. The reviewer spotted the filter omission, re-ran the four enrichment queries with the correct predicate, and the corroborating evidence dissolved.
Senior Reviewer Verdict GAPS IDENTIFIED · METHODOLOGY ERROR
“The investigation built an APT28 narrative on top of already-resolved benign alerts.”

The 30-day lookback queries in Gate 2 did not filter by status_id. The initial 24h query correctly used status_id = NEW. The enrichment queries dropped this filter. This caused the investigation to treat already-resolved, benign-classified alerts as active threats.

Every single APT/malware detection across all four investigated hosts has been resolved by the source platform. The source platforms (Microsoft Defender / Azure Security Center via SecLake) investigated these detections and classified them as benign, likely false positives or signature-matched benign files.

Recommendation: withdraw APT28 attribution. Re-disposition as Standard. Focus on the 9 “Unfamiliar sign-in” alerts and behavioral persistence alerts that remain genuinely status_id = NEW.

What Changed

Severity moved down. The evidence moved with it.

First-pass
Critical · 9.2
Sustained APT28 / YTTRIUM campaign. 30+ days of activity. Recommend immediate IR, network isolation, credential reset across 9 users, forensic imaging.
After review
Standard · 4.5
9 identity alerts remain actionable. Likely explanations include IT change (MFA rollout, VPN change), device refresh, or standard credential anomaly. Investigate, do not mobilize IR.

When Q5 through Q8 were re-run with status_id = NEW, the corroborating evidence for APT28 attribution disappeared. The table below shows what the agent counted as confirmation:

Detection familyStatus (verified)Vendor dispositionCount (4 hosts)
Dukozy high-severity malware RESOLVED Benign ~8
Seadask high-severity malware RESOLVED Benign ~7
YTTRIUM Actor activity detected RESOLVED Benign ~12
YTTRIUM malicious file detected RESOLVED Benign ~18
Bladabindi backdoor detected RESOLVED Benign ~8
Total APT/malware alerts ALL RESOLVED ALL BENIGN ~53

Three categories of alerts remained status_id = NEW and genuinely actionable after the corrected query set:

  1. The 9 “Unfamiliar sign-in properties” alerts. The original trigger pattern. Still requires investigation, but at standard, not APT, severity.
  2. Behavioral / persistence detections (~30 per host) with status_detail = "UnsupportedAlertType". The SecLake integration cannot auto-resolve these alert types; they remain NEW by default. They need triage, but the NEW status is not evidence of malicious intent.
  3. CrowdStrike operational alerts with status_id = null. Mostly operational noise (PrinterInstaller, browser activity, msiexec).
Final Disposition

Standard investigation. Not a nation-state campaign.

The corrected investigation withdraws all APT28 / YTTRIUM attribution claims. The reviewer blocked the original report from distribution and published a revised disposition with the following recommended actions:

  • Contact the 9 affected users to verify whether sign-in activity was legitimate.
  • Check for recent IT changes (MFA rollout, VPN reconfiguration, device refresh) that could explain unfamiliar sign-in properties across multiple users at once.
  • Deploy Azure AD authentication log connector to enable proper sign-in investigation. Current data lacks source IP, geolocation, and MFA status.
  • Triage a sample of “UnsupportedAlertType” persistence alerts to determine whether status_id = NEW is meaningful here or simply a gap in the SecLake integration’s status handling.
  • If any user confirms they did NOT sign in, escalate that specific account for credential-compromise investigation.

Estimated cost avoided by the reviewer’s catch: 40–80 person-hours of incident response mobilization, plus the operational disruption of credential resets and forensic imaging across 9 hosts.

01

Always check status_id on enrichment queries.

The Gate 1 intake query correctly filtered by status_id = NEW. The filter was dropped for the 30-day lookbacks. That single omission caused the entire investigation to reach the wrong conclusion. The fix is structural: shared FSQL rules now enforce status_id filtering on any detection-record query whose result feeds a verdict.

02

Vendor detection labels are not confirmed threats.

“Dukozy malware detected” means the vendor matched a signature. It does not mean Dukozy is confirmed present, especially when the same vendor later resolved it as benign. Disposition state is part of the evidence, not metadata to be ignored.

03

Volume is not evidence.

~600 alerts sounds alarming but is meaningless without signal-to-noise separation and status verification. The investigator weighted record count toward confidence; the reviewer reduced 600 to ~14 actionable records by adding one predicate.

04

Absence of enrichment data is itself a finding.

No file hashes, no Azure AD authentication logs, no on-prem network flow data. These are not blockers to be worked around. They are evidence-quality limits that must be stated explicitly rather than filled with assumptions.

Queries, sources & gaps

All 14 FSQL queries executed

Q1 Pull new HIGH/CRITICAL/FATAL detection findings (24h) CORRECT FILTER
QUERY detection_finding.message, detection_finding.severity_id, detection_finding.time, detection_finding.observables, detection_finding.attacks, detection_finding.status_id, detection_finding.activity_id, detection_finding.finding_info, detection_finding.metadata.product WITH detection_finding.severity_id IN HIGH, CRITICAL, FATAL AND detection_finding.status_id = NEW AFTER 24h
10 results — 9 “Unfamiliar sign-in properties” + 1 SSM compliance alert (200+ when expanded)
Q3 Extract user/IP from all 9 sign-in alerts CORRECT FILTER
QUERY detection_finding.time, detection_finding.observables, detection_finding.evidences.actor.user.domain, detection_finding.evidences.dst_endpoint.ip WITH detection_finding.message = ‘Unfamiliar sign-in properties’ AND detection_finding.status_id = NEW AFTER 24h
9 results — 9 distinct users across BD / DC / NY office prefixes, all 172.16.16.x internal IPs
Q5 30-day history for BD-2578 (ronald.b***), 172.16.16.60 MISSING FILTER
QUERY detection_finding.message, detection_finding.time, detection_finding.severity_id WITH detection_finding.evidences.dst_endpoint.ip = ‘172.16.16.60’ AFTER 30d // status_id = NEW filter not present
39 results as-run (treated as active) · 5 results when re-run with status_id=NEW filter (1 identity + 4 behavioral)
Q6 30-day history for BD-2773 (steven.n***), 172.16.16.44 MISSING FILTER
QUERY detection_finding.message, detection_finding.time, detection_finding.severity_id WITH detection_finding.evidences.dst_endpoint.ip = ‘172.16.16.44’ AFTER 30d // status_id = NEW filter not present
~140 results as-run (Seadask, Dukozy, Bladabindi, YTTRIUM Actor activity, port-scans from 10.100.21.239) · all APT/malware records RESOLVED/Benign on re-query
Q7–Q8 30-day history for BD-2395 and BD-991, same pattern MISSING FILTER
// Same predicate pattern. Same omission. ~150 and ~180 results respectively; // dominated by RESOLVED/Benign APT and malware family records. QUERY detection_finding.message, detection_finding.time, detection_finding.severity_id WITH detection_finding.evidences.dst_endpoint.ip = ‘172.16.16.34’ AFTER 30d
~330 results total across both hosts as-run · ~14 NEW alerts on re-query (all behavioral or identity)
Q10 Inventory check on 10.100.21.239 (suspected pivot) EMPTY RESULT
QUERY inventory_info.host.name, inventory_info.host.ip, inventory_info.os.name WITH inventory_info.host.ip = ‘10.100.21.239’
0 results — host not registered in CrowdStrike, not in Google Workspace Directory. Likely a network appliance not covered by endpoint agents. Downgraded from “potential pivot” to “investigate separately.”
Q11–Q14 Threat-intel enrichment attempts (file hashes, malware family lookups) DATA GAP
// Attempted OSINT enrichment on the detection findings. // File hash fields (file, process.file, evidences.file, evidences.process.file) all empty arrays. // Connector queries against malware family names returned field-path errors — // connectors expect IOC values (IPs, hashes, domains), not family names.
Enrichment not possible with available data. The SecLake detection findings lack the granularity needed for independent threat-intel verification. The agent cannot independently confirm or refute APT attribution beyond the vendor labels — which were already resolved as benign.

Showing 7 of 14 queries above. Full query trail with results in queries.md.

Sources queried · with status

SourceStatusNotes
detection.alerts (SecLake)HITPrimary intake; 600+ records over 30d
edr.crowdstrikePARTIALDetections present; FDR Auth ingestion empty; connector verification needed
identity.azureadGAPNo authentication logs ingested; cannot verify sign-in source IP, geo, MFA status
identity.gws (Google Workspace Directory)HITUser-host correlation; 10.100.21.239 not found
inventory.cmdbHITHost registration check
network.flow (on-prem)GAPNo flow data for 172.16.16.x or 10.100.21.x; cannot trace lateral movement
osint (threat-intel connectors)GAPCannot enrich without IOC-grade evidence (hashes, IPs, domains absent from records)

Gaps explicitly catalogued

  • Azure AD authentication logs not ingested. Root-cause investigation of the 9 sign-in alerts cannot proceed without source IP, geo, and MFA detail.
  • CrowdStrike FDR Auth empty. Cannot correlate endpoint logon events with the identity alerts. Connector ingestion to verify.
  • No on-premises network flow data for 172.16.16.x or 10.100.21.x. Lateral movement paths cannot be traced.
  • File hashes absent from detection findings. Threat-intel enrichment not possible against the source records as ingested.
  • 5 of 9 hosts not deep-dived. NY-2752, BD-1310, DC-2097, DC-1659, BD-2578 covered at 24h trigger only. Recommend extending if any user confirms unauthorized sign-in.

MITRE ATT&CK · what was attributed vs. what holds

TechniqueTacticStatus after review
T1078Initial Access · Valid AccountsPossible, pending sign-in verification with affected users
T1059Execution · Command and ScriptingResolved/Benign, vendor disposition
T1546 / T1543 / T1053 / T1037Persistence · multipleNEW status, but “UnsupportedAlertType”; needs triage to determine if integration artifact or real
T1036Defense Evasion · MasqueradingNEW status with same caveat as above
T1082 / T1016 / T1018 / T1046Discovery · multipleNEW status with same caveat as above