Agent skill

Incident Investigation

by SCStelz in SCStelz/security-investigator

A skill your agent uses when asked to investigate a security incident by ID from Microsoft Defender XDR or Microsoft Sentinel.

MITAuto-check passedSecurity

Install Incident Investigation

skills CLI
$ npx skills add SCStelz/security-investigator --skill incident-investigation -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install SCStelz/security-investigator incident-investigation --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/SCStelz/security-investigator.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.github/skills/incident-investigation .claude/skills/incident-investigation && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
incident-investigation
GitHub stars
249
Token cost
~13k tokens
SKILL.md length
5,121 words
Files
1
Skills in repo
22
Repo updated
First seen
Licence
MIT

At a glance

A skill your agent uses when asked to investigate a security incident by ID from Microsoft Defender XDR or Microsoft Sentinel.

  • Works in 7 steps: Incident Description → Incident Investigation Menu → A: User Investigation → …
  • Asked to investigate a security incident by ID from Microsoft Defender XDR
  • SKILL.md covers Purpose, 📑 TABLE OF CONTENTS, ⚠️ CRITICAL WORKFLOW RULES -… and Phase 1: Incident Description, plus 6 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Incident Investigation is an agent skill from SCStelz/security-investigator. Use this skill when asked to investigate a security incident by ID from Microsoft Defender XDR or Microsoft Sentinel. Triggers on keywords like "investigate incident", "incident ID", "incident investigation", "analyze incident", "triage incident", or when an incident number/ID is mentioned with investigation context. This skill provides comprehensive incident analysis including metadata retrieval, alert listing, asset enumeration, evidence filtering, and deep entity investigation using Sentinel MCP tools and…

Its SKILL.md is about 13k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Security, covering Security operations and MCP servers. It works with Microsoft Defender and Microsoft Sentinel. The repository describes itself as: Automated security investigation tool using Microsoft MCP Servers, GitHub Copilot, Python Modules and custom copilot-instructions. The licence is MIT.

When your agent uses it

  • Asked to investigate a security incident by ID from Microsoft Defender XDR
  • Microsoft Sentinel
  • Keywords like investigate incident
  • Incident investigation

Example prompts

  • “investigate incident”
  • “incident ID”
  • “incident investigation”
  • “/incident-investigation”

Workflow steps

7 steps, taken from the step headings in SKILL.md.

  1. Incident Description
  2. Incident Investigation Menu
  3. A: User Investigation
  4. B: Device Investigation
  5. C: IoC Investigation
  6. Post-Investigation Loop (MANDATORY)
  7. Final Summary & Verdict Gates

What it can do on your machine

Read from SKILL.md and the folder at commit 51e1385. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are kql, markdown and json).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • security.microsoft.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Incident Investigation loads about 13k tokens when it runs. Until then it costs about 139 tokens; SKILL.md has 5,121 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~139
When it runs · the whole SKILL.md, loaded when a task matches
~13k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from SCStelz/security-investigator at commit 51e1385, republished under its MIT licence (© SCStelz). 5,121 words, ~12,932 tokens.

Download SKILL.mdSave it as .claude/skills/incident-investigation/SKILL.md (or your agent's skills folder).
name
incident-investigation
description
Use this skill when asked to investigate a security incident by ID from Microsoft Defender XDR or Microsoft Sentinel. Triggers on keywords like "investigate incident", "incident ID", "incident investigation", "analyze incident", "triage incident", or when an incident number/ID is mentioned with investigation context. This skill provides comprehensive incident analysis including metadata retrieval, alert listing, asset enumeration, evidence filtering, and deep entity investigation using Sentinel MCP tools and specialized skills.
threat_pulse_domains
incidents
drill_down_prompt
Investigate incident {entity} — alert cohesion sweep, entity investigation, verdict gates

Incident Investigation - Instructions

Purpose

This skill performs comprehensive security investigations on incidents from Microsoft Defender XDR and Microsoft Sentinel. It retrieves incident details, lists alerts, enumerates assets and evidences, and then performs deep investigation on user-selected entities using appropriate tools and specialized skills.

Investigation Flow:

  1. Phase 1: Incident Description - Retrieve metadata, alerts, assets, and evidences
  2. Phase 1.5: Alert Cohesion & Adjacent-Alert Sweep - Verify the incident's alerts belong together, and sweep for related alerts left outside it
  3. Phase 2: Incident Investigation Menu - Ask the user to select the incident assets and entities that should be investigated.
  4. Phase 2-A: User Investigation - Follow user-investigation skill workflow
  5. Phase 2-B: Device Investigation - Follow computer-investigation skill workflow
  6. Phase 2-C: IoC Investigation - Follow ioc-investigation skill workflow for IPs, URLs, Files, Domains, Hashes
  7. Phase 3: Post-Investigation Loop - Offer any remaining entities; skip straight to Phase 4 when nothing material remains
  8. Phase 4: Final Summary & Verdict Gates - Pass all four verdict gates before writing any classification

📑 TABLE OF CONTENTS

  1. Critical Workflow Rules - Start here!
  2. Phase 1: Incident Description - Metadata, Alerts, Assets, Evidences
  3. Phase 1.5: Alert Cohesion & Adjacent-Alert Sweep - Scope correction before investigating
  4. Phase 2: Incident Investigation Menu - Presenting the options
  5. Phase 2-A: User Investigation - Using user-investigation skill
  6. Phase 2-B: Device Investigation - Using computer-investigation skill
  7. Phase 2-C: IoC Investigation - Using ioc-investigation skill (IPs, URLs, Files, Domains, Hashes)
  8. Phase 3: Post-Investigation Loop - Offer remaining entities, or skip to Phase 4
  9. Phase 4: Final Summary & Verdict Gates - Baseline, alternatives, attribution, negative findings
  10. JSON Export Structure - Required fields
  11. Error Handling - Troubleshooting guide

⚠️ CRITICAL WORKFLOW RULES - READ FIRST ⚠️

Before starting ANY incident investigation:

  1. ALWAYS complete Phase 1 first - Retrieve full incident description before any deep investigation
  2. ALWAYS list Sentinel workspaces at the START of Phase 2 - Call list_sentinel_workspaces MCP tool BEFORE presenting the investigation menu
  3. ⛔ ALWAYS complete workspace selection BEFORE any investigation - This is a MANDATORY CHECKPOINT:
    • If 1 workspace: auto-select and display to user
    • If multiple workspaces: ASK USER to select and WAIT for response
    • DO NOT proceed to any entity investigation without a workspace selected
  4. ALWAYS present extracted entities to user - After workspace selection, ask user which entities to investigate
  5. ALWAYS wait for user confirmation - Do not proceed with deep investigation until user selects entities
  6. ALWAYS use the correct tools for each entity type:
    • Users → Follow .github/skills/user-investigation/SKILL.md
    • Devices → Follow .github/skills/computer-investigation/SKILL.md
    • IPs/URLs/Files/Domains/Hashes → Follow .github/skills/ioc-investigation/SKILL.md
  7. ALWAYS track and report time after each major step
  8. ALWAYS filter evidences - Remove internal IPs (RFC1918) and tenant domains from investigation scope. Also remove all public IPs from the devices listed as assets involved in the incident.
    • Validate infrastructure IPs empirically, not by rule. A CIDR range alone is a hypothesis; cross-account prevalence is evidence. Run the IP Prevalence Check before dismissing any IP as shared infrastructure, CGNAT, VPN egress, or a proxy — and state which method you used.
  9. ALWAYS defang malicious/suspicious URLs and IPs - NEVER return them as clickable links. Use defang format: hxxps://evil[.]com, 203[.]0[.]113[.]42
  10. ⛔ NEVER auto-select a Sentinel workspace when multiple exist - Workspace selection is MANDATORY:
    • ❌ DO NOT select a workspace on behalf of the user when multiple exist
    • ❌ DO NOT switch to another workspace if a query fails
    • ❌ DO NOT proceed with investigation without explicit user selection
    • ✅ If query fails: STOP, report error, ask user to select different workspace
    • ✅ If multiple workspaces: STOP, list all, WAIT for user selection
    • ✅ Only auto-select if exactly ONE workspace exists
  11. ALWAYS run the alert cohesion check before Phase 2 - Incidents can fuse unrelated activity. Verify the alerts share entities; if they form disjoint clusters, investigate and verdict each cluster separately. De-correlated ≠ dismissed (see Phase 1.5)
  12. ALWAYS establish a baseline before labelling behaviour anomalous - No entity may be described as anomalous, unusual, or compromised without a stated 14–30 day baseline (see Phase 4 Gate 1)
  13. ALWAYS pass all four Verdict Gates before writing a classification - Baseline, alternative hypotheses, attribution evidence, negative findings (see Phase 4)

Incident ID Patterns:

PatternSourceTool to Use
Numeric (e.g., 12345, 98765)Defender XDR / SentinelGetIncidentById
GUID formatSentinel (internal)Sentinel query_lake MCP tool
INxx-xxxxx formatDefender XDRGetIncidentById

⚠️ Sentinel → Defender XDR ID Mapping (Critical):

When an incident is discovered via Sentinel KQL (e.g., SecurityIncident or SecurityAlert tables), its IDs are Sentinel-local and will NOT work with the Triage MCP:

Sentinel FieldTriage MCP Accepts?Correct Field to Use
SecurityIncident.IncidentNumber❌ Returns "not found"Use SecurityIncident.ProviderIncidentId
SecurityAlert.SystemAlertId❌ Returns "not found"Extract parse_json(ExtendedProperties).IncidentId
SecurityIncident.ProviderIncidentId✅Pass directly to GetIncidentById

Rule: When querying SecurityIncident for later Triage MCP drill-down, always project ProviderIncidentId alongside IncidentNumber. Use ProviderIncidentId for all GetIncidentById calls.

Date Range Rules:

  • Default analysis window: 7 days before current date to current date (Standard)
  • Investigation depth options:
    • Comprehensive: 30 days window (for thorough analysis)
    • Standard: 7 days window (default)
    • Quick: 1 day window (for rapid triage)
  • Format: ISO 8601 (e.g., 2026-01-17T00:00:00Z to 2026-01-24T00:00:00Z)
IP Prevalence Check

Confirm whether an IP appears across many unrelated accounts in the window. This is the empirical test behind Critical Rule 8.

kql
let TargetIPs = dynamic(["<ip1>","<ip2>"]);
EntraIdSignInEvents
| where Timestamp between (datetime(<start>) .. datetime(<end>))
| where IPAddress in (TargetIPs)
| summarize DistinctAccounts = dcount(AccountUpn), SignIns = count(),
            Days = dcount(bin(Timestamp, 1d)), SampleAccounts = make_set(AccountUpn, 5)
          by IPAddress
| order by DistinctAccounts desc

Run in Advanced Hunting

ResultInterpretation
High DistinctAccounts across many DaysShared infrastructure — proven. Overrides a Defender roles: ["attacker"] tag and beats an ASN lookup or a 0% AbuseIPDB score, which only describe the IP's owner, not its use in this tenant
DistinctAccounts == 1Singleton — NOT shared infrastructure. The "corporate egress / shared jump host / VPN pool" benign hypothesis is eliminated, not unresolved (Gate 2)
No row returnedThe IP was never seen in sign-in telemetry. Find which source did observe it (AlertEvidence, CloudAppEvents) before citing it as a session IP

Feed each result into Gate 1 — an entity whose baseline is mostly singleton IPs behaves differently from one that lives on shared infrastructure.

Report only the counts this query returned. Never supplement, substitute, or "remember" which accounts share an IP — a co-occurrence recalled from cached context is a hypothesis, and writing it into a column labelled as query output converts it into false evidence.


Phase 1: Incident Description

This phase retrieves and presents all incident information. Follow the exact structure below.

1.1 Incident Metadata

Retrieve and list the incident's metadata using GetIncidentById:

FieldDescription
TitleIncident display name
DescriptionDetailed incident description
StatusActive, Resolved, Redirected
SeverityHigh, Medium, Low, Informational
Priority assessmentIf available from incident data
ClassificationTruePositive, FalsePositive, BenignPositive, etc.
DeterminationMalware, Phishing, etc.
Created DateWhen incident was created
First Activity DateFirst malicious activity timestamp
Last Updated DateMost recent modification
Assigned ToAnalyst assigned to incident
MITRE CategoriesTactics and techniques involved
TagsLabels applied to incident
1.2 Incident Alerts
🔴 Tool Selection for Alert Retrieval

Use GetIncidentById with includeAlertsData=true to retrieve incident-specific alerts. This returns only alerts correlated to the incident.

⛔ DO NOT use ListAlerts to retrieve alerts for a specific incident. ListAlerts has NO incidentId parameter — it can only filter by createdAfter, createdBefore, severity, status. Calling it returns all tenant alerts (up to page size 10,000), not incident-specific ones. Any unsupported parameter (e.g., incidentId) is silently ignored.

If GetIncidentById(includeAlertsData=true) returns a truncated or excessively large response (e.g., incident has hundreds of correlated alerts from noise sources like Purview IRM or DLP), use RunAdvancedHuntingQuery as the fallback:

kql
// Get alerts linked to the incident's primary user/entity
AlertInfo
| where Timestamp > datetime(<incident_created_minus_7d>)
| join kind=inner (
    AlertEvidence
    | where Timestamp > datetime(<incident_created_minus_7d>)
    | where EntityType == "User"
    | where AccountUpn =~ "<primary_user_upn>" or AccountObjectId == "<user_object_id>"
    | distinct AlertId
) on AlertId
| project Timestamp, AlertId, Title, Severity, Category, AttackTechniques, DetectionSource, ServiceSource
| order by Timestamp asc

This approach bypasses the Triage MCP's alert cap and gives full control over date range and entity filtering.

Alert Fields to Retrieve

For each alert, retrieve:

  • Alert name
  • Tags
  • Severity
  • Investigation state
  • Status
  • Classification (TruePositive / FalsePositive / BenignPositive / unknown)
  • Determination (Malware, Phishing, SecurityTesting, NotMalicious, etc.)
  • Impacted assets
  • Correlation reason
  • Detection source
  • First activity
  • Last activity

🔴 Surface pre-existing determinations. Classification and Determination are often already populated by a prior analyst or by automated investigation. Show them in the alert table and treat them as evidence — an alert already marked notMalicious materially changes the weight of that alert. Do not silently re-litigate a closed determination; either corroborate it or state explicitly why you disagree.

Presentation Rules:

  1. Return as a table (exclude the Alert ID column from display — but retain the IDs, Phase 1.5's sweep needs them)
  2. Order by last activity date descending
  3. Add row numbers starting from 1
  4. If more than 30 alerts exist, note this after the table and provide a Defender portal link
  5. NEVER calculate and write the total number of alerts
  6. Add a Disposition column and fill it in once Phase 2 completes. Every alert must exit the investigation with exactly one of:
DispositionMeaning
Supports verdictInvestigated; corroborates the cluster verdict
Ruled out — <reason>Investigated; explained by a benign cause. State the reason inline
Not investigatedOutside the selected scope. Must also appear in Phase 3's remaining-entities list

No alert may be silently dropped. An alert missing from the final table is an unaccounted-for detection.

1.3 Incident Assets

Retrieve and list ALL assets involved in the incident by type:

Device Assets:

FieldDescription
NameDevice hostname
DomainAD domain
Risk LevelDevice risk assessment
Exposure LevelVulnerability exposure
OS PlatformOperating system

User Assets:

FieldDescription
Display NameUser's full name
UPNUser Principal Name
User StatusAccount status
DomainUser's domain
DepartmentOrganizational department

App Assets:

FieldDescription
App NameApplication name
App Client IDOAuth client ID
RiskApplication risk level
PublisherApp publisher

Cloud Resource Assets:

FieldDescription
Resource NameCloud resource identifier
StatusResource status
Cloud EnvironmentAzure, AWS, GCP, etc.
TypeResource type

Count assets by type ONLY after retrieving complete lists.

1.4 Incident Evidences

Retrieve evidences classified as malicious or suspicious only:

Processes (Top 10):

  • Get ALL malicious/suspicious processes
  • Return only the 10 most probable signs of malicious activity (use judgment)

Files (Top 10):

  • Get ALL malicious/suspicious files
  • Return only the 10 most probable signs of malicious activity (use judgment)

IP Addresses (Top 10, Filtered):

  • Get ALL malicious/suspicious IPs
  • Filter out RFC1918 internal IPs: 10.x.x.x, 172.16-31.x.x, 192.168.x.x
  • Filter out public IPs associated to the devices listed as assets involved in the incident
  • Return only the first 10 from filtered list
  • DEFANG ALL IPs: When presenting IPs and domains to the user, ALWAYS use defanged format: 203[.]0[.]113[.]42, evil[.]com. NEVER output clickable malicious indicators.

URLs and DNS Domains (Top 10, Filtered):

  • Get ALL malicious/suspicious URLs and DNS Domains
  • Filter out tenant domain URLs (DNS domains associated with the organization)
  • Return only the first 10 from filtered list
  • DEFANG ALL URLs AND DNS DOMAINS: When presenting URLs to the user, ALWAYS use defanged format: hxxps://evil[.]com/path, hxxp://malware[.]net. NEVER output clickable malicious URLs.

AD Domains:

  • Return ALL malicious/suspicious AD domains (no limit)

For each evidence type: If more than 10 exist, note this after the table and provide Defender portal link.


1.5 Alert Cohesion & Adjacent-Alert Sweep

Incident correlation is fallible in both directions: it can fuse unrelated activity into one incident, and it can leave related alerts outside it. Run both checks before Phase 2 so the investigation scope is correct from the start.

(a) Cohesion Check — do these alerts belong together?

Group the incident's alerts by shared entity (user, device, IP, session/correlation ID) and present the clusters:

ClusterAlertsShared EntitiesTime Span
A4user1@contoso.com, 203[.]0[.]113[.]422026-01-20 04:07 → 04:15
B7user2@contoso.com, 198[.]51[.]100[.]102026-01-14 08:00 → 08:01
  • Single cluster (all alerts share ≥1 entity) → proceed normally, one verdict for the incident.
  • ≥2 disjoint clusters (zero shared entities) AND >24h gap between them → ⚠️ flag probable spurious correlation. Investigate each cluster independently and issue a separate verdict per cluster in Phase 4.

🔴 De-correlated ≠ dismissed. A cluster found not to relate to the seed alert is never dropped — it either receives its own verdict in this report or is explicitly handed off as a new investigation. Report the correlation defect itself as a finding: it is actionable detection-engineering feedback regardless of whether the underlying activity was malicious.

(b) Adjacent-Alert Sweep — is anything missing?

The incident's alert list is not the full picture of what its entities did. Sweep for alerts that touch an incident entity but were not correlated into the incident:

kql
let IncidentAlertIds = dynamic(["<alertId1>", "<alertId2>"]);   // from GetIncidentById
let IncidentEntities = dynamic(["user1@contoso.com", "203.0.113.42", "HOST-01"]);
let IncidentObjectIds = dynamic(["<userObjectId1>"]);           // more reliable than UPN
let WindowStart = datetime(<incident_created_minus_7d>);
let WindowEnd   = datetime(<incident_last_activity_plus_1d>);
AlertEvidence
| where Timestamp between (WindowStart .. WindowEnd)
| where AccountUpn in~ (IncidentEntities)
    or AccountObjectId in (IncidentObjectIds)
    or RemoteIP in (IncidentEntities)
    or DeviceName in~ (IncidentEntities)
| where AlertId !in (IncidentAlertIds)
| distinct AlertId
| join kind=inner (
    AlertInfo
    | where Timestamp between (WindowStart .. WindowEnd)
) on AlertId
| project Timestamp, Title, Severity, Category, DetectionSource, ServiceSource, AttackTechniques
| order by Timestamp asc

Run in Advanced Hunting

Tool: RunAdvancedHuntingQuery — the default 7d window is well within the 30d AH limit. For windows >30d use mcp_sentinel-data_query_lake and swap Timestamp → TimeGenerated.

⛔ Mandatory — no substitutes. Prior investigations, cached context, or a high-confidence early verdict tell you how to interpret what this sweep returns; none of them tell you what it would have returned. Run it every time and state the row count, including zero.

Report either outcome:

  • Alerts found → add them to scope, present in a table, and note that the platform did not correlate them into the incident.
  • None found → state it explicitly: "✅ No additional alerts involving incident entities in [window]."
  • Query not executed → the result line MUST read "⚠️ Not executed — sweep incomplete". ✅ asserts a zero row count you do not have.

Phase 2: Incident Investigation Menu

⛔ MANDATORY CHECKPOINT: Workspace Selection

This checkpoint MUST be completed before ANY entity investigation can proceed.

Step 2.1: List Sentinel Workspaces

ALWAYS execute this step first, regardless of any other considerations:

list_sentinel_workspaces (MCP tool)

Store the result. This determines the workflow for Step 2.3.

Step 2.2: Present Entity Summary

Show a summary of the incident entities and assets from Phase 1:

  • Users (with UPN and display name)
  • Devices (with hostname and risk level)
  • URLs (defanged)
  • IPs (defanged, filtered)
  • File hashes
  • Domains (defanged)

🔴 Defang every URL, domain, and IP (Critical Rule 9) — hxxps://evil[.]com/path, evil[.]com, 203[.]0[.]113[.]42. Never output clickable malicious indicators.

Step 2.3: Workspace Selection Gate
IF workspace_count == 1:
    - Auto-select the single workspace
    - Display: "Using Sentinel workspace: [NAME] ([ID])"
    - Set SESSION_WORKSPACE_SELECTED = true
    
ELSE IF workspace_count > 1 AND SESSION_WORKSPACE_SELECTED == false:
    - Display all workspaces with Name and ID
    - ASK USER: "Which Sentinel workspace should I run my searches in? Select one or more, or choose 'all'."
    - WAIT for user response
    - Set SESSION_WORKSPACE_SELECTED = true after selection
    
ELSE IF workspace_count > 1 AND SESSION_WORKSPACE_SELECTED == true:
    - Display: "Continuing with previously selected workspace: [NAME] ([ID])"
    - DO NOT ask again
⛔ DO NOT PROCEED PAST THIS POINT WITHOUT A WORKSPACE SELECTED

If SESSION_WORKSPACE_SELECTED == false after Step 2.3, STOP and ask the user to select a workspace.

Step 2.4: Ask User to Select Entities

Ask the user:

"Which assets and entities involved in the incident should be investigated in depth? Please select them by providing their numbers or names, or simply ask to analyze all of them. The more entities you select, the longer the analysis will take."

🔴 DO NOT OFFER OTHER OPTIONS: Only ask the user whether they want to investigate one or more of the incident entities and assets listed above in more depth.

Read the response.

  • If they do not want to proceed with the proposed investigations, ask them what they want to do.
  • If they want to proceed with one or more of the proposed investigations, continue with Step 2.5.
Step 2.5: Start Investigations

Pre-flight check: Confirm SESSION_WORKSPACE_SELECTED == true before proceeding.

Proceed in accordance with the instructions described below for Phase 2-A, Phase 2-B, and Phase 2-C. When multiple investigation types are selected (users, devices, IoCs) run them in parallel as much as possible.

Evidence Capture Standard (applies to ALL Phase 2 investigations)

Per-event detail is what makes a verdict defensible and a cluster separation provable. For every event cited as evidence, capture:

TelemetryCapture
Sign-inCorrelationId/RequestId, SessionId, ResultType/ErrorCode, RiskLevelDuringSignIn, RiskEventTypes, device managed + compliant state and DeviceId, user agent, ClientAppUsed, AuthenticationRequirement
Graph / APIOperation, HTTP method, ResponseStatusCode, response size where the platform exposes it (MicrosoftGraphActivityLogs.ResponseSizeBytes), request URI, calling app/SPN identity
Cloud appActionType, AccountObjectId, IPAddress, user agent, and the specific RawEventData fields cited (parse once into a variable — never tostring(RawEventData) has ...)
Device / processDeviceId, initiating-process chain, SHA256, signer/publisher, FolderPath, command line

Why these specifically:

  • HTTP method + response size discriminate enumeration from a single UI lookup. A small, single-object read is not reconnaissance no matter which API served it — do not map it to a discovery technique without volume or response-size support.
  • Managed/compliant state + risk level are prerequisites for any compromise verdict. An unfamiliar IP on a compliant, managed device with no risk detection is a materially different finding from the same IP on an unmanaged one.
  • Correlation / request / session IDs are what make cross-table pivots and the cluster separation in §1.5 provable rather than asserted.
  • Success/failure ratio across the whole event set — always record it. High-volume access with zero authentication failures argues strongly against credential guessing or brute force.

🔴 Validate the central artefact at its source. When an alert's premise rests on a specific artefact, query the authoritative table for that artefact directly. Never infer its nature from the alert title.

ArtefactAuthoritative sourceReport verbatim
EmailEmailEvents by NetworkMessageIdThreatTypes, DetectionMethods, DeliveryAction, DeliveryLocation, EmailDirection, AuthenticationDetails
URL clickUrlClickEvents by Url / NetworkMessageIdActionType, IsClickedThrough, UrlChain
FileDeviceFileEvents or GetDefenderFileInfo by hashGlobalPrevalence, signer, FirstSeen
Sign-inSigninLogs / EntraIdSignInEvents by CorrelationIdResultType, RiskLevelDuringSignIn, CA outcome

The platform's own disposition outranks the alert title. An alert named "phish delivered" whose EmailEvents row shows empty ThreatTypes, empty DetectionMethods, and DeliveryAction: Delivered was not a detected phish. Say so, and record the discrepancy itself as a finding.


Phase 2-A: User Investigation

Pre-requisites (MANDATORY)

⛔ VERIFY BEFORE PROCEEDING:

  • ✅ SESSION_WORKSPACE_SELECTED == true (workspace explicitly selected by user)
  • ✅ SELECTED_WORKSPACE_IDS array is populated with user's selection
  • ✅ User has explicitly selected which user(s) to investigate

If any pre-requisite is FALSE: STOP and return to Phase 2.3 Workspace Selection Gate.

User Investigation Workflow

⚡ PARALLEL EXECUTION: When multiple users are selected, execute user investigations in parallel as much as possible.

📦 WORKSPACE CONTEXT: Pass the selected workspace(s) to all child skill invocations:

  • Use SELECTED_WORKSPACE_IDS from Phase 2.3 for all Sentinel queries
  • If a query fails with table/workspace error: STOP, report error, ask user to select different workspace
  • ⛔ DO NOT automatically retry with a different workspace

For EACH user selected by the user:

🔴 REFERENCE THE SKILL FILE: Read and follow the complete workflow defined in:

.github/skills/user-investigation/SKILL.md

Key Steps (summary - see skill file for full details):

  1. Get User Object ID from Microsoft Graph
  2. Calculate date ranges based on investigation type (Standard/Quick/Comprehensive)
  3. Run parallel data collection:
    • Sign-in anomalies (Signinlogs_Anomalies_KQL_CL — note lowercase 'l' in "logs")
    • Sign-in statistics (apps, locations, IPs)
    • Audit log events
    • Office 365 activity
    • Security incidents involving user
    • Identity Protection risk detections
    • MFA and authentication methods
    • Device compliance status
  4. IP enrichment for flagged addresses
  5. Compile and present findings
  6. Generate HTML report (if requested)

DO NOT copy the full workflow here - always read the skill file for the most current instructions.


Phase 2-B: Device Investigation

Device Investigation Workflow

⚡ PARALLEL EXECUTION: When multiple devices are selected, execute device data collection queries in parallel for ALL devices simultaneously. Run Defender alerts, compliance, logged-on users, vulnerabilities, network/process/file events queries concurrently.

For EACH device selected by the user:

🔴 REFERENCE THE SKILL FILE: Read and follow the complete workflow defined in:

.github/skills/computer-investigation/SKILL.md

Key Steps (summary - see skill file for full details):

  1. Get Device IDs (Entra Device ID + Defender Device ID)
  2. Determine device type (Entra Joined, Hybrid Joined, Entra Registered)
  3. Run parallel data collection:
    • Defender alerts for device
    • Device compliance status
    • Logged-on users
    • Software vulnerabilities
    • Network connections
    • Process events
    • File events
    • Automated investigations
  4. Compile and present findings

DO NOT copy the full workflow here - always read the skill file for the most current instructions.


Show full SKILL.md (2,049 more words)Show less

Phase 2-C: IoC Investigation

IoC Investigation Workflow

⚡ PARALLEL EXECUTION: When multiple IoCs are selected, execute ALL IoC investigation queries in parallel. Run threat intel lookups, Sentinel queries, and organizational exposure queries concurrently for all IoCs.

For EACH IoC selected by the user:

🔴 REFERENCE THE SKILL FILE: Read and follow the complete workflow defined in:

.github/skills/ioc-investigation/SKILL.md

Supported IoC Types:

IoC TypeDetection PatternKey Investigation Points
URLhttps?:// or domain patternMalicious indicators, phishing, threat intel, organizational exposure
IPv4 Address\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}Threat intel, network connections, geographic analysis
IPv6 AddressContains multiple colonsSame as IPv4
Domain[a-zA-Z0-9][-a-zA-Z0-9]*\.[a-zA-Z]{2,}DNS queries, email threats, reputation
MD5 Hash32 hex charactersFile prevalence, malware analysis
SHA1 Hash40 hex charactersFile prevalence, malware analysis
SHA256 Hash64 hex charactersFile prevalence, malware analysis

Key Steps (summary - see skill file for full details):

  1. Identify IoC type and normalize
  2. Query Defender Threat Intelligence
  3. Check Sentinel ThreatIntelIndicators table
  4. Analyze organizational exposure (devices, connections)
  5. Correlate with CVEs if applicable
  6. Present findings with risk assessment

DO NOT copy the full workflow here - always read the skill file for the most current instructions.


Phase 3: Post-Investigation Loop (MANDATORY)

⛔ CRITICAL: DO NOT END THE RESPONSE WITHOUT COMPLETING THIS PHASE

After completing ALL selected entity investigations in Phase 2, first check whether the loop is needed at all:

ConditionAction
Material entities remain uninvestigatedRun the loop below
No material entities remain — all investigated, or the remainder were filtered out in §1.4 as internal/tenant-owned⏭️ Skip to Phase 4. Never present an empty "remaining entities" table
User requested a complete / one-shot investigation (e.g. "investigate incident X and write the report", "investigate everything")⏭️ Skip to Phase 4. The loop exists to confirm scope, not to withhold the verdict

When the loop IS needed, you MUST:

  1. List remaining uninvestigated entities - Show all entities from Phase 1 that were NOT yet investigated
  2. Ask the user to select additional entities - Prompt user to continue or conclude
  3. Wait for user response - Do not assume the investigation is complete
Phase 3 Checklist (when the loop is needed)
☐ Step 3.1: Compile list of UNINVESTIGATED entities (exclude already-investigated items)
☐ Step 3.2: Present remaining entities to user with numbered list
☐ Step 3.3: Ask: "Would you like to investigate any of the remaining entities? Select by number/name, or say 'done' to conclude."
☐ Step 3.4: Wait for user response before concluding
Required Prompt Format

When the loop is needed, end the findings with:

📋 Remaining Uninvestigated Entities:

#TypeEntityNotes
1Device[DEVICE_NAME][Risk level or relevant context]
2File[FILENAME][Hash or detection status]
3URL[DEFANGED_URL][Threat assessment]
............

Would you like to investigate any of these remaining entities? Select by number/name, type "all" to investigate everything, or say "done" to conclude the investigation.

Rules
  • DO NOT include entities that were already investigated in the list
  • DO NOT ask the user to select Sentinel workspaces again (use previously selected workspace)
  • DO NOT conclude while material entities remain unoffered — but this is a scoping gate, not a requirement that the user utter a magic word. When nothing material remains, proceed to Phase 4 on your own initiative
  • DO NOT assume the investigation is complete just because selected entities were analyzed
Loop Behavior
IF no material entities remain
   OR a complete / one-shot investigation was requested:
    → Proceed to Phase 4 directly — do NOT present the list, do NOT ask first

ELSE present the remaining-entities list, then:

    IF user selects additional entities:
        → Return to Phase 2 (2-A, 2-B, or 2-C based on entity type)
        → After completion, return to Phase 3 again

    ELSE IF user says "done" or declines:
        → Proceed to Phase 4 (Final Summary & Verdict Gates)

Phase 4: Final Summary & Verdict Gates

Entry condition — reached by ANY of the following:

  • The user says "done" or declines further investigation in Phase 3
  • No material entities remain uninvestigated (Phase 3 loop skipped)
  • The user requested a complete or one-shot investigation up front (e.g. "investigate incident X and write me the report")
  • The user asks for a verdict, classification, summary, or report at any point

🔴 Phase 4 is never optional and never waits for permission. Any output that states a classification — inline in chat, in a report file, or in a recorded finding — must have passed these gates first.

⛔ Four Gates — ALL must pass before writing any classification
Gate 1 · Baseline

For every entity you are about to call anomalous, unusual, or compromised, pull 14–30 days of prior activity and diff it against the flagged activity across: application set, source IPs/geography, operation mix, volume, and success/failure ratio.

State the baseline explicitly in the report — including when it is absent (new account, no prior telemetry, retention exceeded).

💡 A source IP that is new to an entity is novelty. A source IP that is new and carries operations absent from the baseline and breaks the normal volume envelope is anomaly. Only the second justifies escalation.

Diff the pattern, not only the value. When a value is new, also ask how often this entity acquires new values of that attribute. If the baseline shows a recurring acquisition rate — a fresh short-lived source IP every 7–10 days, a new device each month — then the next new value is baseline-consistent, not novel. A correct value-level diff still yields a wrong verdict when the rate of change is itself the norm. Classify each baseline value by prevalence (Rule 8) so the pattern is described accurately.

ActionStatus
Calling behaviour "reconnaissance", "anomalous", "unusual", or "malicious" with no stated baseline❌ PROHIBITED
Labelling a value "novel" without checking how often the entity acquires new values of that attribute❌ PROHIBITED
A baseline diff before any behavioural verdict✅ REQUIRED
Gate 2 · Alternative Hypotheses

State at least one competing benign explanation and resolve it with evidence:

HypothesisSupporting EvidenceContradicting EvidenceVerdict
Automation / service workloadSame user agent present on baseline activity—✅ Accepted
Credential compromiseSource IP new to this entity0 auth failures; compliant managed device; no risk detection❌ Rejected

Include this table even when the malicious hypothesis wins — it demonstrates the alternative was tested rather than ignored.

Gate 3 · Attribution Evidence

Words like "attacker", "threat actor", "adversary", "malicious", and "compromised" require at least one of:

  1. A threat-intel / reputation hit on the indicator
  2. An observed malicious action — write, exfiltration, persistence, privilege change
  3. Independent corroboration from a second telemetry source

Unfamiliarity is not attribution. A new IP, a new user agent, or a first-seen app is novelty, not adversary presence.

Attribution confidence must never exceed overall verdict confidence. If the verdict is "inconclusive", the infrastructure cannot be described as "attacker-controlled".

Gate 4 · Negative Findings

Explicitly enumerate what was searched for and not found. Silence is not evidence of absence — state what you checked:

  • Persistence (app registrations, credential adds, role grants, scheduled tasks)
  • Privilege escalation (role assignments, consent grants, PIM activations)
  • Mailbox manipulation (forwarding rules, inbox rules, delegation)
  • Exfiltration (bulk download/export, unusual data access volume)
  • Control-plane writes (resource creation/deletion, policy changes)
  • Lateral movement (new device or resource access)
  • Endpoint execution (process, file, script events)

Also state telemetry gaps — tables unavailable, licences absent, retention exceeded — so a reader can distinguish "checked and clean" from "could not check".

Verdict Block Format

Emit one block per cluster identified in §1.5 — not one blended verdict for the whole incident.

Use plain headings and bullets, matching the rest of the report. Do not wrap verdict blocks in blockquotes or code fences — Gate 2's hypothesis table and any supporting evidence tables must nest beneath the block without a > prefix on every row.

markdown
#### Cluster A — `<entity>` · `<verdict>` 🟢 / 🟡 / 🟠 / 🔴

- **Classification:** TruePositive / BenignPositive / FalsePositive / Inconclusive
- **Confidence:** High / Medium / Low
- **Baseline:** *one line — what normal looks like for this entity*
- **Decisive evidence:** *1–3 bullets*
- **Not found:** *negative-findings summary*
- **Recommendation:** *action, or "no action required"*

After the last cluster block, close with an #### Overall Assessment heading in the same idiom — not a loose bold line — carrying the cross-cluster risk statement. Then provide consolidated recommendations across clusters and offer the JSON export.


Sentinel MCP Tools Reference

analyze_user_entity

Purpose: Starts asynchronous security analysis of a user entity.

Parameters:

ParameterTypeRequiredDescription
userIdstringYesUser's Azure AD Object ID (GUID)
startTimestringYesISO 8601 format start time
endTimestringYesISO 8601 format end time
workspaceIdstringNoSentinel workspace GUID (optional if only one workspace)

Time Window Options: 30 days (Comprehensive), 7 days (Standard), 1 day (Quick)

Returns: 202 Accepted with analysisId

get_entity_analysis

Purpose: Retrieves results of an asynchronous entity analysis.

Parameters:

ParameterTypeRequiredDescription
analysisIdstringYesAnalysis ID returned from analyze_*_entity

Returns: 200 OK with analysis results when complete, or status if still processing


Quick Start (TL;DR)

When a user requests an incident investigation:

  1. Phase 1 - Incident Description:

    • Retrieve incident metadata using GetIncidentById
    • List top 30 alerts as a table (include Classification / Determination)
    • Enumerate all assets by type (devices, users, apps, cloud resources)
    • List filtered evidences (processes, files, IPs, URLs, domains)
  2. Phase 1.5 - Alert Cohesion & Adjacent Sweep:

    • Cluster the incident's alerts by shared entity; flag spurious correlation if disjoint
    • Sweep for related alerts left outside the incident
    • De-correlated ≠ dismissed — each cluster gets its own verdict
  3. ⛔ Phase 2 - Mandatory Workspace Selection:

    • Call list_sentinel_workspaces MCP tool FIRST
    • Present entity summary from Phase 1
    • If 1 workspace: auto-select and display
    • If multiple workspaces: ASK USER to select before proceeding
    • DO NOT proceed to investigations without a workspace selected
  4. Phase 2-A - User Investigation:

    • For each selected user: Follow .github/skills/user-investigation/SKILL.md
    • Present findings
  5. Phase 2-B - Device Investigation:

    • For each selected device: Follow .github/skills/computer-investigation/SKILL.md
    • Present findings
  6. Phase 2-C - IoC Investigation:

    • For each selected IoC (IPs, URLs, Files, Domains, Hashes): Follow .github/skills/ioc-investigation/SKILL.md
    • Present findings
    • Apply the Evidence Capture Standard to every cited event (IDs, device posture, HTTP method + response size, success/failure ratio)
  7. Phase 3 - Post-Investigation Loop:

    • List uninvestigated entities and ask whether to continue
    • Skip straight to Phase 4 if nothing material remains, or a complete/one-shot investigation was requested
  8. Phase 4 - Final Summary & Verdict Gates:

    • Gate 1 Baseline · Gate 2 Alternative hypotheses · Gate 3 Attribution evidence · Gate 4 Negative findings
    • Emit one verdict block per cluster, then consolidated recommendations
    • Create consolidated JSON file

JSON Export Structure

Required Fields
FieldTypeDescription
investigation_metadataobjectIncident ID, timestamp, phases completed, elapsed time
incident_detailsobjectMetadata, alerts (each with disposition), assets, evidences from Phase 1
clustersarrayPhase 1.5 output — one entry per cohesion cluster, with member alert IDs, shared entities, and separation evidence
user_investigationsarrayResults from Phase 2-A (includes the stated baseline)
device_investigationsarrayResults from Phase 2-B
ioc_investigationsarrayResults from Phase 2-C (IPs, URLs, files, domains, hashes)
verdictsarrayPhase 4 — one verdict block per cluster, each carrying its four gate results
summaryobjectOverall risk assessment, consolidated recommendations, negative findings
Example JSON Structure
json
{
  "investigation_metadata": {
    "incident_id": "<INCIDENT_ID>",
    "investigation_timestamp": "<ISO_TIMESTAMP>",
    "phases_completed": ["incident_description", "cohesion_check", "user_investigation", "ioc_investigation", "verdict"],
    "total_elapsed_time_seconds": 300
  },
  "incident_details": {
    "metadata": {
      "title": "<TITLE>", "severity": "<SEVERITY>", "status": "<STATUS>",
      "classification": "<CLASSIFICATION>", "determination": "<DETERMINATION>",
      "created_date": "<TIMESTAMP>", "first_activity_date": "<TIMESTAMP>",
      "mitre_categories": ["<TACTIC>"], "tags": ["<TAG>"]
    },
    "alerts": [
      {
        "id": "<ALERT_ID>", "name": "<ALERT_NAME>", "severity": "<SEVERITY>",
        "classification": "<PRE_EXISTING_CLASSIFICATION>", "determination": "<PRE_EXISTING_DETERMINATION>",
        "first_activity": "<TIMESTAMP>", "last_activity": "<TIMESTAMP>",
        "cluster": "A",
        "disposition": "Ruled out — mailbox is a lab honeypot; no click, no credential entry"
      }
    ],
    "assets": { "devices": [], "users": [], "apps": [], "cloud_resources": [] },
    "evidences": { "processes": [], "files": [], "ip_addresses": [], "urls": [], "ad_domains": [] }
  },
  "clusters": [
    {
      "id": "A", "label": "<SHORT_LABEL>", "alert_ids": ["<ALERT_ID>"],
      "shared_entities": ["user@contoso.com"],
      "time_span": { "start": "<TIMESTAMP>", "end": "<TIMESTAMP>" },
      "linked_to_other_clusters": false,
      "separation_evidence": "No shared UPN, IP, DeviceId, or SessionId with cluster B; 6 days apart",
      "sweep_performed": true,
      "uncorrelated_adjacent_alerts": 3
    }
  ],
  "user_investigations": [
    {
      "upn": "user@contoso.com", "user_id": "<GUID>",
      "time_window": { "start": "<ISO_TIMESTAMP>", "end": "<ISO_TIMESTAMP>" },
      "baseline": {
        "window_days": 30, "typical_ips": [], "typical_countries": [],
        "typical_apps": [], "typical_devices": []
      },
      "findings": {}, "risk_level": "Low"
    }
  ],
  "device_investigations": [
    { "hostname": "<DEVICE_NAME>", "device_id": "<GUID>", "findings": {} }
  ],
  "ioc_investigations": [
    {
      "ioc_type": "IP", "value": "203.0.113.42",
      "prevalence": { "distinct_accounts": 553, "days": 30 },
      "threat_assessment": "Shared infrastructure — not attacker-controlled",
      "findings": {}
    }
  ],
  "verdicts": [
    {
      "cluster": "A",
      "classification": "BenignPositive",
      "determination": "SecurityTesting",
      "confidence": "High",
      "gates": {
        "baseline": "30-day baseline established; all observed IPs and apps fall within it",
        "alternatives_considered": [
          {
            "hypothesis": "Credential theft via phish",
            "status": "Eliminated",
            "evidence": "No click in UrlClickEvents; no sign-in from sender infrastructure"
          }
        ],
        "attribution_evidence": "EmailEvents shows empty ThreatTypes and DetectionMethods — no platform detection backs the alert title",
        "negative_findings": ["No mailbox rule creation", "No OAuth consent grant", "No sign-in risk detection"]
      },
      "recommendations": []
    }
  ],
  "summary": {
    "risk_assessment": "Low",
    "key_findings": [],
    "negative_findings": [],
    "recommendations": []
  }
}

Error Handling

Common Issues and Solutions
IssueSolution
Incident not foundVerify incident ID format; try Sentinel query if Defender fails
User Object ID not foundVerify UPN is correct; check if user exists in Entra ID
analyze_user_entity returns errorCheck userId is GUID format; verify time window ≤ 30 days
get_entity_analysis still processingPoll again after 5-10 seconds; max 2 minutes
No workspace foundUse list_sentinel_workspaces MCP tool to get workspace ID
Device investigation failsVerify device exists in Defender; check device ID type
IoC investigation timeoutReduce date range; check IoC format
Workspace Selection

See Phase 2 Step 2.3. Do not restate or re-derive the rule — and never re-ask once SESSION_WORKSPACE_SELECTED == true.


Example Investigation Workflow

User Request: "Investigate incident 12345"

⚠️ This example is deliberately abbreviated. It exists to show the shape of a compliant investigation — specifically the Phase 1.5 clustering table and the Phase 4 verdict blocks. Do not copy findings or phrasing from it.

Phase 1 — Incident Description

Retrieve metadata via GetIncidentById, then present alerts, assets, and filtered evidences per §1.1–§1.4. The alert table carries Classification, Determination, and the Disposition column (completed at the end of Phase 2).

Phase 1.5 — Alert Cohesion & Adjacent Alert Sweep
[01:30] Cohesion check — 7 alerts

| Cluster | Alerts | Shared entities                     | Time span                   |
|---------|--------|-------------------------------------|-----------------------------|
| A       | 5      | jsmith@contoso.com, WORKSTATION-01  | Jan 20 10:30 – Jan 20 14:05 |
| B       | 2      | svc-backup@contoso.com              | Jan 14 03:12 – Jan 14 03:14 |

Separation evidence: no shared UPN, IP, DeviceId, or SessionId between A and B; 6 days apart.
→ Investigate and verdict A and B SEPARATELY. De-correlated ≠ dismissed.

Sweep: 3 further alerts on cluster-A entities in the ±7d window were NOT correlated into
the incident (2 × Purview DLP, 1 × sign-in risk). Both clusters' entity sets swept.
Phase 2 — Investigation

Workspace gate → entity selection → run 2-A / 2-B / 2-C in parallel, applying the Evidence Capture Standard to every cited event. Validate central artefacts at source: EmailEvents by NetworkMessageId, hash prevalence via GetDefenderFileInfo, and IPs via the IP Prevalence Check.

A cited event carries its identifiers, not just its label — e.g. "GET /v1.0/me/messages?$search=… → 200, ResponseSizeBytes 1,204,880, 312 calls in 4 min by app <AppDisplayName>", not "mail enumeration detected". The same rule governs the negative: "no exfiltration found" requires showing the operations you looked at, otherwise it is an assumption.

Phase 3 — Post-Investigation Loop

Two entities remained uninvestigated (SERVER-DC01, jdoe@contoso.com); neither was material to either cluster, so the loop was skipped and the reason stated. Both are recorded with disposition: "Not investigated".

Phase 4 — Verdict Blocks (one per cluster)
━━━ Cluster A — WORKSTATION-01 / jsmith@contoso.com ━━━
Classification: TruePositive   Determination: Malware   Confidence: High

Gate 1 — Baseline (30d): jsmith signs in from 2 IPs, both AS12345 corporate egress,
  always from WORKSTATION-01, always compliant + managed. The Jan 20 session came from a
  singleton IP (DistinctAccounts = 1), an unmanaged device, ClientAppUsed = Other.
Gate 2 — Alternatives: VPN/travel ELIMINATED (no travel record; device unmanaged).
  Shared egress ELIMINATED (prevalence = 1 account). Admin tooling ELIMINATED (no PIM activation).
Gate 3 — Attribution: SHA256 abc123… GlobalPrevalence = 4, unsigned, written to %TEMP%;
  DeviceNetworkEvents shows 42 outbound beacons to 203[.]0[.]113[.]42 at 60s intervals.
Gate 4 — Negative findings: no lateral movement; no LSASS access events; no mailbox rule
  creation; no OAuth consent grant.

━━━ Cluster B — svc-backup@contoso.com ━━━
Classification: BenignPositive   Determination: SecurityTesting   Confidence: High

Gate 1 — Baseline (30d): identical ~3-minute burst at 03:12 every weekday, same IP, same app.
Gate 2 — Alternatives: compromise ELIMINATED (100% success ratio, zero auth failures,
  no off-schedule activity across the full 30d window).
Gate 3 — Attribution: scheduled backup job; user agent and app ID match documented automation.
Gate 4 — Negative findings: no scope expansion; no new credentials added to the SPN.

Consolidated recommendations follow the verdict blocks, each tagged with its cluster and severity.

Export: temp/incident_investigation_12345_<date>.json


Integration with Skill Files

This skill orchestrates investigations by referencing specialized skills:

Investigation PhaseSkill/ToolLocation/Reference
Phase 1: Incident DescriptionBuilt-in workflowThis file (see Phase 1 section)
Phase 1.5: Alert Cohesion & SweepBuilt-in workflowThis file (see §1.5)
Phase 2-A: User Investigationuser-investigation skill.github/skills/user-investigation/SKILL.md
Phase 2-B: Device Investigationcomputer-investigation skill.github/skills/computer-investigation/SKILL.md
Phase 2-C: IoC Investigationioc-investigation skill.github/skills/ioc-investigation/SKILL.md (IPs, URLs, Files, Domains, Hashes)
Phase 4: Verdict GatesBuilt-in workflowThis file (see Phase 4 section)

🔴 ALWAYS read the referenced skill file before executing that phase to ensure proper workflow execution.

© SCStelz, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .github/skills/incident-investigation of SCStelz/security-investigator.

Open the folder on GitHubat commit 51e1385

Compare with similar skills

Incident Investigation next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Incident Investigation compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Incident Investigation this skillSCStelz/security-investigator249—~13kAutomated safety check: PassMIT
Sentinelvinayaklatthe/microsoft-security-skills175—~2.2kAutomated safety check: PassMIT
Unified Secops Platformvinayaklatthe/microsoft-security-skills175—~2.1kAutomated safety check: PassMIT
Defender Xdrvinayaklatthe/microsoft-security-skills175—~2.1kAutomated safety check: PassMIT
Detecting Azure Service Principal Abusemukul975/Anthropic-Cybersecurity-Skills34k—~2.1kAutomated safety check: PassApache-2.0
Detecting Service Account Abusemukul975/Anthropic-Cybersecurity-Skills34k—~904Automated safety check: PassApache-2.0

Similar skills

  • Sentinel

    vinayaklatthe/microsoft-security-skills

    Guidance for designing and operating Microsoft Sentinel, the cloud-native SIEM and SOAR delivered through the Defender portal.

    175 GitHub stars~2.2k tokensUpdated 3 mo ago
    SecurityAuto-check passed
  • Unified Secops Platform

    vinayaklatthe/microsoft-security-skills

    Guidance for the Microsoft unified security operations platform that brings Microsoft Sentinel, Microsoft Defender XDR, Security Copilot, Threat Intelligence, and Microsoft Security Exposure…

    175 GitHub stars~2.1k tokensUpdated 3 mo ago
    SecurityAuto-check passed
  • Defender Xdr

    vinayaklatthe/microsoft-security-skills

    Guidance for Microsoft Defender XDR — the unified extended detection and response suite that correlates signals across endpoints, identities, email, and cloud apps into prioritised incidents with…

    175 GitHub stars~2.1k tokensUpdated 3 mo ago
    Backend & APIsAuto-check passed
  • Detecting Azure Service Principal Abuse

    mukul975/Anthropic-Cybersecurity-Skills

    Detect Azure service principal abuse in Microsoft Entra ID using KQL detection queries (Sentinel/Splunk) against Azure AD Audit and Sign-in Logs, covering added credentials, privileged role…

    34k GitHub stars~2.1k tokensUpdated 1 mo ago
    SecurityAuto-check passed
  • Detecting Service Account Abuse

    mukul975/Anthropic-Cybersecurity-Skills

    Detect abuse of service accounts by hunting for anomalous interactive logons, privilege escalation, and lateral movement using EDR/SIEM telemetry (CrowdStrike Falcon, Microsoft Defender, Splunk…

    34k GitHub stars~904 tokensUpdated 1 mo ago
    SecurityAuto-check passed
  • Detecting Suspicious Powershell Execution

    mukul975/Anthropic-Cybersecurity-Skills

    Hunt for suspicious PowerShell execution (T1059.001) such as encoded commands, download cradles, AMSI bypass, and constrained language mode evasion using EDR telemetry (CrowdStrike, Microsoft…

    34k GitHub stars~923 tokensUpdated 1 mo ago
    SecurityAuto-check passed

More from SCStelz/security-investigator

All 22 skills in this repo
  • Ca Policy Investigation

    SCStelz/security-investigator

    A skill your agent uses when asked to investigate Conditional Access policy changes, sign-in failures related to CA policies (error codes 53000, 50074, 530032), or suspected policy…

    249 GitHub stars~3.8k tokensUpdated 2 days ago
    Auto-check passed
  • Context Memory Review

    SCStelz/security-investigator

    Weekly review of an investigation tenant-context memory file against the most recent SOC scan reports (e.g.

    249 GitHub stars~3.7k tokensUpdated 2 days ago
    Auto-check passed
  • Heatmap Visualization

    SCStelz/security-investigator

    A skill your agent uses when asked to create heatmaps, visualize patterns over time, show activity grids, or display aggregated data in a matrix format.

    249 GitHub stars~3.4k tokensUpdated 2 days ago
    Auto-check passed
  • AI Agent Activity

    SCStelz/security-investigator

    Report/investigate RUNTIME ACTIVITY of AI agents (Agent 365 / Copilot Studio / M365 Copilot / Work IQ) — agents used, tools/connectors, channels, tokens, prompt/reply content, and Prompt Shield…

    249 GitHub stars~17k tokensUpdated 2 days ago
    Auto-check passed
  • AI Agent Posture

    SCStelz/security-investigator

    Audit or report on AI agent security posture across Copilot Studio, Microsoft 365 Copilot, Microsoft Foundry, and third-party agents.

    249 GitHub stars~21k tokensUpdated 2 days ago
    Auto-check passed
  • App Registration Posture

    SCStelz/security-investigator

    Audit Entra ID app registration and service principal security posture.

    249 GitHub stars~21k tokensUpdated 2 days ago
    Auto-check passed

Questions about Incident Investigation

What does Incident Investigation do?

A skill your agent uses when asked to investigate a security incident by ID from Microsoft Defender XDR or Microsoft Sentinel. Incident Investigation is an agent skill from SCStelz/security-investigator. Use this skill when asked to investigate a security incident by ID from Microsoft Defender XDR or Microsoft Sentinel.

When should I use Incident Investigation?

Incident Investigation fits situations like: asked to investigate a security incident by ID from Microsoft Defender XDR; microsoft Sentinel; keywords like investigate incident; incident investigation.

How do I install Incident Investigation in Claude Code?

Run `npx skills add SCStelz/security-investigator --skill incident-investigation -a claude-code`. Or copy the skill folder (.github/skills/incident-investigation in SCStelz/security-investigator) into .claude/skills/incident-investigation in your project. Claude Code loads it when a task matches its description.

How do I install Incident Investigation in Codex?

Run `npx skills add SCStelz/security-investigator --skill incident-investigation -a codex`. Or copy the skill folder (.github/skills/incident-investigation in SCStelz/security-investigator) into .agents/skills/incident-investigation in your project. Codex loads it when a task matches its description.

Can I use Incident Investigation in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add SCStelz/security-investigator --skill incident-investigation -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/incident-investigation, .gemini/skills/incident-investigation, .github/skills/incident-investigation and .opencode/skills/incident-investigation in your project.

What does Incident Investigation need to run?

SKILL.md names no scripts, command-line tools or credentials: Incident Investigation is instructions for the agent only.

Does Incident Investigation access the network?

SKILL.md names 1 domain. As links in the text: security.microsoft.com. This is read from the text; nothing was executed.

Is Incident Investigation safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Incident Investigation use?

Incident Investigation is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Incident Investigation use?

About 13k tokens (SKILL.md is roughly 52k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Incident Investigation?

Skills that share tags, products or a category with Incident Investigation: Sentinel (vinayaklatthe/microsoft-security-skills, 175 stars), Unified Secops Platform (vinayaklatthe/microsoft-security-skills, 175 stars), Defender Xdr (vinayaklatthe/microsoft-security-skills, 175 stars) and Detecting Azure Service Principal Abuse (mukul975/Anthropic-Cybersecurity-Skills, 34k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Incident Investigation?

SCStelz (a GitHub user) maintains it in SCStelz/security-investigator, which has 249 GitHub stars. The repository holds 22 skills in this directory. The repository was last updated on October 8, 2026.

Source: SCStelz/security-investigator on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.