Entra ID Assistive Agent Impersonation
An adversary has gained initial access by tricking a user into consenting to an assistive agent blueprint, then used an on-behalf-of flow to execute malicious Graph API actions from a macOS-based PowerShell environment.
Based on research by Red Canary 2026-09-20 12 steps · 5 queries T1059.001 T1098 T1528 T1567
Brief
Why this hunt?
Red Canary recently highlighted risks in Entra ID Assistive Agents in their post: Investigating suspicious AI workflows in Microsoft Entra Agent ID: Assistive agents (https://redcanary.com/blog/threat-detection/entra-id-ai-workflows-assistive-agents/). These agents allow automated workflows to act on behalf of users, creating a stealthy path for impersonation and data exfiltration. As organizations adopt AI-driven automation, protecting the integrity of Entra Agent ID becomes critical to prevent automated workflows from being used as exfiltration channels.
How the Hunt Flows
The hunt starts with scoping. The first query on hb_software_inventory lists every macOS host running Microsoft PowerShell (pwsh) to define the target environment where the malicious execution is possible. The identity phase then pivots to hb_auth_signin logs. We search for authentications to the Microsoft Graph Command Line Tools followed by rare sign-ins to agent blueprints or assistive agents used by three or fewer users. This combination suggests a user has granted delegated permissions that an agent is now using for automated tasks. The execution phase moves to the endpoint to correlate identity risk with local activity. We examine hb_process_activity on the scoped macOS hosts to find rare PowerShell command lines that deviate from the established baseline. This activity is then corroborated with hb_network_connection logs to identify traffic reaching graph.microsoft.com or known malicious IPs. A final triage step synthesizes the identity risk, the rare macOS PowerShell execution, and the Graph network activity into a single cohesive story of impersonation.
Blind Spots
The primary limitation is telemetry depth in standard logs. Entra ID sign-in metadata may not always expose the deep agenticAppInstance flags needed to distinguish OBO flows from standard service principal usage without high-fidelity cloud-native logs. Additionally, while the hunt identifies network traffic to the Graph API, the specific intent and actions performed—such as which files were accessed or which emails were sent—remain opaque without Microsoft Graph Activity Logs, which require specific subscription tiers.
Steps
-
Find macOS hosts with PowerShell installed
Query · scopingIdentify the subset of the estate where the malicious execution (PowerShell on macOS) is possible.
reads hb_software_inventorysqlSELECT device_hostname, package_name, package_version FROM hb_software_inventory WHERE (LOWER(package_name) = 'powershell' OR LOWER(package_name) = 'pwsh') AND LOWER(vendor_name) LIKE '%microsoft%'What a hit looks like. A list of macOS hostnames with Microsoft PowerShell installed. These hosts represent the potential beachheads for the macOS execution stage.
-
Identify Graph CLI authentication
Query · triageLocate authentications to the Graph CLI application, which often precedes the local capture of authorization codes.
reads hb_auth_signinsqlSELECT actor_user_name, src_endpoint_ip, dst_endpoint_name, time FROM hb_auth_signin WHERE (dst_endpoint_name = '{{graph_cli_app_id}}' OR LOWER(dst_endpoint_name) LIKE '%microsoft graph command line%') AND time >= datetime('now', '-{{lookback_days}} days')What a hit looks like. A list of users who have authenticated to the Graph CLI. This is the pool of potentially compromised users who may have granted agent consent.
-
Detect agentic OBO sign-in patterns
Query · baselineStack-count sign-ins to agent blueprints to find rare and suspicious assistive agent activity across the tenant.
reads hb_auth_signinsqlSELECT dst_endpoint_name, COUNT(DISTINCT actor_user_name) as user_count, MIN(time) as first_seen FROM hb_auth_signin WHERE (LOWER(dst_endpoint_name) LIKE '%blueprint%' OR LOWER(dst_endpoint_name) LIKE '%agent%') AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY dst_endpoint_name HAVING user_count <= 3What a hit looks like. Rare agent blueprint targets. While some agents are legitimate, those used by only a few users are high-priority for investigation.
-
Evaluate early identity risk
Agent triageAssess whether the Graph CLI authentication and rare agent sign-ins indicate a user impersonation event via assistive agents.
-
Detect rare macOS PowerShell execution
Query · baselineFind outlier PowerShell activity on macOS that may indicate the execution of agent-controlled tasks.
reads hb_process_activitysqlSELECT device_hostname, process_cmd_line, user_name, COUNT(DISTINCT device_hostname) as host_count, MIN(time) as first_seen FROM hb_process_activity WHERE (LOWER(process_name) LIKE '%pwsh%' OR LOWER(process_path) LIKE '%pwsh%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY process_cmd_line HAVING host_count <= 3What a hit looks like. PowerShell command lines seen on very few hosts. This filters out common IT scripts and focuses on unique, potentially malicious activity.
-
Correlate network connections to Microsoft Graph
Query · enrichmentCorroborate that the identified macOS hosts and PowerShell processes are communicating with Graph API or known malicious IPs.
reads hb_network_connectionsqlSELECT device_hostname, process_name, dst_endpoint_hostname, dst_endpoint_ip, time FROM hb_network_connection WHERE (LOWER(dst_endpoint_hostname) LIKE '%graph.microsoft.com%' OR instr(',' || '{{malicious_ips}}' || ',', ',' || dst_endpoint_ip || ',') > 0) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')What a hit looks like. Network activity from identified hosts to Graph API endpoints, confirming that the local execution has a corresponding cloud-side impact.
-
Final attack chain triage
Agent triageSynthesize the identity risk, rare macOS PowerShell execution, and Graph network activity into a single cohesive story of impersonation.
-
Route on final verdict
DecisionDirectional decision based on the triage of the full attack chain.
-
Isolate host and revoke tokens
Response actionContain the breach by isolating the endpoint and terminating the agentic session.
-
Remediate and perform analyst review
Analyst taskPerform manual validation of the agentic actions and remediate any remaining persistence.
-
Close out investigation
Analyst taskFinalize the hunt when no malicious impersonation is found.
Coverage
Scenario coverage
| Stage | Covered | How, or why not |
|---|---|---|
| OAuth Consent for Assistive Agent T1098 |
Yes | identify-graph-cli-auth |
| On-Behalf-Of Token Acquisition T1528 |
Yes | detect-agentic-obo-signins, evaluate-early-identity-risk |
| Execution via PowerShell on macOS T1059.001 |
Yes | rare-macos-powershell-execution |
| Unauthorized Email via Graph API T1567 |
Yes | correlate-network-to-graph |
Blind spots
- Needs Detailed Entra Sign-in Metadata such as Agent.agentType. Standard authentication logs may not expose the deep agentic flags needed to distinguish OBO from standard service principal usage without high-fidelity cloud-native logs. It would answer Was the authentication explicitly an OBO flow using an agenticAppInstance?.
- Needs MicrosoftGraphActivityLogs. While network traffic to graph.microsoft.com is visible, the specific intent is hidden without access to Graph activity logging, which requires specific subscription tiers. It would answer What specific actions did the agent perform via the API?.
Parameters & data
Parameters
| Parameter | Type | Default | What it is |
|---|---|---|---|
graph_cli_app_id | string | 14d82eec-204b-4c2f-b7e8-296a70dab67e | The Entra client application ID for Microsoft Graph Command Line Tools used for consent. |
lookback_days | number | 14 | Days of history to examine. |
malicious_ips | list[ip] | 51.3.97.221, 40.126.23.26 | IP addresses observed in the report associated with agentic sign-ins and malicious actions. |
scope_hosts | list[host] | — | Optional list of hostnames to focus the endpoint phase on; derived from the scoping step. |
Telemetry
| Source | Category | Telemetry |
|---|---|---|
| Endpoint telemetry (hb_ surfaces) | endpoint | endpoint |
| Identity / sign-in telemetry | identity | identity |
| Network telemetry | network | network |
Source
---
analysis: A simple detection rule might catch PowerShell on macOS, but it cannot link
that activity back to an Entra ID consent grant and an agentic on-behalf-of flow.
This hunt correlates identity-side consent with endpoint-side execution outliers
across multiple planes.
blind_spots:
- id: limited-agentic-telemetry
question: Was the authentication explicitly an OBO flow using an agenticAppInstance?
requires: Detailed Entra Sign-in Metadata such as Agent.agentType
risk: Standard authentication logs may not expose the deep agentic flags needed
to distinguish OBO from standard service principal usage without high-fidelity
cloud-native logs.
stage: agent-token-impersonation
- id: graph-operation-opacity
question: What specific actions did the agent perform via the API?
requires: MicrosoftGraphActivityLogs
risk: While network traffic to graph.microsoft.com is visible, the specific intent
is hidden without access to Graph activity logging, which requires specific subscription
tiers.
stage: graph-api-malicious-action
coverage:
- stage: consent-granting-delegated-access
status: covered
steps:
- identify-graph-cli-auth
- stage: agent-token-impersonation
status: covered
steps:
- detect-agentic-obo-signins
- evaluate-early-identity-risk
- stage: powershell-endpoint-execution
status: covered
steps:
- rare-macos-powershell-execution
- stage: graph-api-malicious-action
status: covered
steps:
- correlate-network-to-graph
guardrails:
claims: no_unsupported
evidence: citation_required
missing_data: not_benign
telemetry: untrusted
hunt:
applicability: campaign-specific
handoff: keep-as-periodic-hunt
justification: The rapid adoption of AI agents creates a new impersonation vector
that bypasses traditional human-centric behavioral monitoring. Protecting Entra
Agent ID integrity ensures that automated workflows are not used as a stealthy
exfiltration channel.
methodology: model-assisted
trigger: intel-report
hypothesis: An adversary has gained initial access by tricking a user into consenting
to an assistive agent blueprint, then used an on-behalf-of flow to execute malicious
Graph API actions from a macOS-based PowerShell environment.
labels:
- hunt
- attack.t1098
- attack.t1528
- attack.t1059.001
- attack.t1567
name: Entra ID Assistive Agent Impersonation
parameters:
graph_cli_app_id:
default: 14d82eec-204b-4c2f-b7e8-296a70dab67e
description: The Entra client application ID for Microsoft Graph Command Line
Tools used for consent.
from:
kind: article
observed: '2026-06-08'
ref: https://redcanary.com/blog/threat-detection/entra-id-ai-workflows-assistive-agents/
type: string
lookback_days:
default: '14'
description: Days of history to examine.
type: number
malicious_ips:
default:
- 51.3.97.221
- 40.126.23.26
description: IP addresses observed in the report associated with agentic sign-ins
and malicious actions.
from:
kind: article
observed: '2026-06-08'
ref: https://redcanary.com/blog/threat-detection/entra-id-ai-workflows-assistive-agents/
type: list[ip]
scope_hosts:
default: []
description: Optional list of hostnames to focus the endpoint phase on; derived
from the scoping step.
type: list[host]
provenance:
authors:
- name: Huntbase hunt generation
org: huntbase.io
generated:
by: huntbase-hunt-generation
from: https://redcanary.com/blog/threat-detection/entra-id-ai-workflows-assistive-agents/
gates:
- dry-run
- lint
- critic
model: hb_google/gemini-3-flash-preview
rationale: Start by identifying all macOS hosts with PowerShell installed. The identity
phase should focus on users who have interacted with the Graph CLI application,
as this is the primary mechanism for establishing the agent identity scope.
references:
- name: 'Investigating suspicious AI workflows in Microsoft Entra Agent ID: Assistive
agents'
url: https://redcanary.com/blog/threat-detection/entra-id-ai-workflows-assistive-agents/
related:
- hunt: oauth-app-consent-abuse
reason: This hunt focuses specifically on assistive agents and Entra Agent ID, not
general OAuth application abuse.
relation: out-of-scope-alternative
scenario:
stages:
- name: OAuth Consent for Assistive Agent
observables:
- access_agent scope
- http://localhost/
- 14d82eec-204b-4c2f-b7e8-296a70dab67e
- Dev Agent Identity Blueprint - NOT FOR PROD
slug: consent-granting-delegated-access
tactic: initial-access
techniques:
- T1098
- name: On-Behalf-Of Token Acquisition
observables:
- agenticAppInstance
- notAgentic
- 8cd0a10f-0be8-413a-9bf2-f44bc568d1e4
- Group.Read.All
- Mail.ReadWrite
- Mail.Send
- MailboxSettings.ReadWrite
slug: agent-token-impersonation
tactic: credential-access
techniques:
- T1528
- name: Execution via PowerShell on macOS
observables:
- Mozilla/5.0 (Macintosh; macOS 26.4.1; en-US) PowerShell/7.6.1
- 51.3.97.221
slug: powershell-endpoint-execution
tactic: execution
techniques:
- T1059.001
- name: Unauthorized Email via Graph API
observables:
- bigwig_CFO@importantcompany.com
- Here is your invoice
- 40.126.23.26
- Microsoft Graph beta API
slug: graph-api-malicious-action
tactic: exfiltration
techniques:
- T1567
summary: Attackers exploit Microsoft Entra Assistive Agents by tricking users into
granting 'access_agent' scopes via OAuth consent, often using localhost-redirect
URIs. This allows the agent to obtain On-Behalf-Of (OBO) tokens to impersonate
the user and perform unauthorized actions, such as sending malicious emails via
the Microsoft Graph API from attacker-controlled environments using PowerShell.
severity: high
targets:
analyst:
name: Tier-2 analyst
role: analyst
endpoint:
category: endpoint
name: Endpoint telemetry (hb_ surfaces)
telemetry:
- endpoint
hunter:
agent: true
name: Hunt agent
identity:
category: identity
name: Identity / sign-in telemetry
telemetry:
- identity
network:
category: network
name: Network telemetry
telemetry:
- network
tlp: clear
type: investigation
---
# Entra ID Assistive Agent Impersonation
This hunt targets the abuse of Microsoft Entra Agent ID, specifically the assistive agent workflow. It follows the attack chain from the initial OAuth consent for the access_agent scope to the final malicious action performed via the Graph API. The hunt identifies high-risk identity sessions and then verifies corresponding endpoint execution. We look for the correlation of unusual Entra ID sign-in patterns, specifically agentic app instances, with endpoint-side PowerShell activity on macOS and corresponding network traffic to Microsoft Graph services.
## find-macos-powershell-hosts
<!-- Find macOS hosts with PowerShell installed -->
Identify the subset of the estate where the malicious execution (PowerShell on macOS) is possible.
```sqlite target=endpoint role=scoping
~~~yaml
expected: A list of macOS hostnames with Microsoft PowerShell installed. These hosts
represent the potential beachheads for the macOS execution stage.
reads:
- device_hostname
- package_name
- package_version
silence: not_evidence_of_absence
source: hb_software_inventory
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, package_name, package_version FROM hb_software_inventory WHERE (LOWER(package_name) = 'powershell' OR LOWER(package_name) = 'pwsh') AND LOWER(vendor_name) LIKE '%microsoft%'
```
## early-stage-parallel
<!-- Investigate identity consent and agentic sign-ins -->
parallel:
- → identify-graph-cli-auth
- → detect-agentic-obo-signins
join: → evaluate-early-identity-risk
## identify-graph-cli-auth
<!-- Identify Graph CLI authentication -->
Locate authentications to the Graph CLI application, which often precedes the local capture of authorization codes.
```sqlite target=identity role=triage params=(graph_cli_app_id=graph_cli_app_id, lookback_days=lookback_days)
~~~yaml
expected: A list of users who have authenticated to the Graph CLI. This is the pool
of potentially compromised users who may have granted agent consent.
reads:
- actor_user_name
- src_endpoint_ip
- dst_endpoint_name
- time
silence: not_evidence_of_absence
source: hb_auth_signin
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT actor_user_name, src_endpoint_ip, dst_endpoint_name, time FROM hb_auth_signin WHERE (dst_endpoint_name = '{{graph_cli_app_id}}' OR LOWER(dst_endpoint_name) LIKE '%microsoft graph command line%') AND time >= datetime('now', '-{{lookback_days}} days')
```
## detect-agentic-obo-signins
<!-- Detect agentic OBO sign-in patterns -->
Stack-count sign-ins to agent blueprints to find rare and suspicious assistive agent activity across the tenant.
```sqlite target=identity role=baseline params=(lookback_days=lookback_days)
~~~yaml
baseline:
compare: first_seen
window: '{{lookback_days}}d'
expected: Rare agent blueprint targets. While some agents are legitimate, those used
by only a few users are high-priority for investigation.
prevalence:
by: actor_user_name
key:
- dst_endpoint_name
rare_below: 3
reads:
- dst_endpoint_name
- actor_user_name
- time
silence: not_evidence_of_absence
source: hb_auth_signin
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT dst_endpoint_name, COUNT(DISTINCT actor_user_name) as user_count, MIN(time) as first_seen FROM hb_auth_signin WHERE (LOWER(dst_endpoint_name) LIKE '%blueprint%' OR LOWER(dst_endpoint_name) LIKE '%agent%') AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY dst_endpoint_name HAVING user_count <= 3
```
## evaluate-early-identity-risk
<!-- Evaluate early identity risk -->
```agent target=hunter
cite: required
context:
- identify-graph-cli-auth
- detect-agentic-obo-signins
max_iterations: 4
objective: Identify users who authenticated to Graph CLI and subsequently initiated
sessions with rare agent blueprints, potentially via OBO flows.
success_criteria: A per-user risk verdict citing the matching sign-in events.
tools:
- endpoint
- identity
- network
```
## follow-on-parallel
<!-- Correlate with macOS execution and network activity -->
parallel:
- → rare-macos-powershell-execution
- → correlate-network-to-graph
join: → final-attack-chain-triage
## rare-macos-powershell-execution
<!-- Detect rare macOS PowerShell execution -->
Find outlier PowerShell activity on macOS that may indicate the execution of agent-controlled tasks.
```sqlite target=endpoint role=baseline params=(scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
baseline:
compare: first_seen
window: '{{lookback_days}}d'
expected: PowerShell command lines seen on very few hosts. This filters out common
IT scripts and focuses on unique, potentially malicious activity.
prevalence:
by: device_hostname
key:
- process_cmd_line
rare_below: 3
reads:
- device_hostname
- process_cmd_line
- user_name
- time
silence: not_evidence_of_absence
source: hb_process_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, process_cmd_line, user_name, COUNT(DISTINCT device_hostname) as host_count, MIN(time) as first_seen FROM hb_process_activity WHERE (LOWER(process_name) LIKE '%pwsh%' OR LOWER(process_path) LIKE '%pwsh%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY process_cmd_line HAVING host_count <= 3
```
## correlate-network-to-graph
<!-- Correlate network connections to Microsoft Graph -->
Corroborate that the identified macOS hosts and PowerShell processes are communicating with Graph API or known malicious IPs.
```sqlite target=network role=enrichment params=(malicious_ips=malicious_ips, scope_hosts=scope_hosts, lookback_days=lookback_days)
~~~yaml
expected: Network activity from identified hosts to Graph API endpoints, confirming
that the local execution has a corresponding cloud-side impact.
reads:
- device_hostname
- process_name
- dst_endpoint_hostname
- dst_endpoint_ip
- time
silence: not_evidence_of_absence
source: hb_network_connection
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, process_name, dst_endpoint_hostname, dst_endpoint_ip, time FROM hb_network_connection WHERE (LOWER(dst_endpoint_hostname) LIKE '%graph.microsoft.com%' OR instr(',' || '{{malicious_ips}}' || ',', ',' || dst_endpoint_ip || ',') > 0) AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days')
```
## final-attack-chain-triage
<!-- Final attack chain triage -->
```agent target=hunter
cite: required
context:
- evaluate-early-identity-risk
- rare-macos-powershell-execution
- correlate-network-to-graph
max_iterations: 6
objective: Determine if the rare endpoint and network activity on macOS was triggered
by the identity-side agent impersonation identified in the first phase.
success_criteria: A malicious/suspicious/benign verdict per host/user pair, citing
specific events from all phases.
tools:
- endpoint
- identity
- network
```
## route-on-verdict
<!-- Route on final verdict -->
if~: "the triage verdict is malicious for at least one host and user pair" (confidence: high, judge=hunter)
then: → isolate-host
indeterminate: → remediate-and-review
unavailable: → remediate-and-review (blind_spot: limited-agentic-telemetry)
else: → close-out-investigation
## isolate-host
<!-- Isolate host and revoke tokens -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the macOS host; revoke the OAuth refresh tokens for the affected user; disable the specific agent identity if possible.
```
→ remediate-and-review
## remediate-and-review
<!-- Remediate and perform analyst review -->
```manual target=analyst
Review Purview/Exchange logs for emails sent by the agent ID. Inspect the endpoint for local PowerShell history or configuration files. Document the initial access vector such as the specific phishing link used for consent.
```
→ end
## close-out-investigation
<!-- Close out investigation -->
```manual target=analyst
Document the identified legitimate agentic workflows. Note the baseline usage of PowerShell on macOS for future tuning.
```
→ end
Run it
Take this hunt into your environment.
Open it in Huntbase to run every step against your own connections, with Scout weighing the evidence and your analysts in command. Or take the open hunt.md file anywhere that reads the format.
Machine-drafted by huntbase-hunt-generation using hb_google/gemini-3-flash-preview, gated by dry-run, lint, critic, then reviewed by a person.