From sentinelone
Executes threat hunting queries using SentinelOne PowerQuery on Singularity Data Lake, explains pipeline syntax, manages time ranges with get_timestamp_range and iso_to_unix_timestamp, analyzes results.
npx claudepluginhub wyre-technology/msp-claude-plugins --plugin sentineloneThis skill uses the workspace's default tool permissions.
PowerQuery is SentinelOne's query language for searching the Singularity Data Lake -- the centralized telemetry repository containing process events, network connections, file operations, registry changes, and other security-relevant data from all managed endpoints and cloud workloads. For MSPs, PowerQuery is the primary tool for deep forensic analysis, threat hunting, and incident investigatio...
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
Calculates TAM/SAM/SOM using top-down, bottom-up, and value theory methodologies for market sizing, revenue estimation, and startup validation.
PowerQuery is SentinelOne's query language for searching the Singularity Data Lake -- the centralized telemetry repository containing process events, network connections, file operations, registry changes, and other security-relevant data from all managed endpoints and cloud workloads. For MSPs, PowerQuery is the primary tool for deep forensic analysis, threat hunting, and incident investigation across client environments.
IMPORTANT: PowerQuery is a Scalyr-based pipeline query language. It is NOT Splunk SPL, SQL, KQL (Kusto), or Elasticsearch Query DSL. The syntax is fundamentally different. The recommended approach is to use the
purple_aitool to generate PowerQuery strings from natural language descriptions, then execute them with thepowerquerytool.
| Tool | Description | Key Parameters |
|---|---|---|
powerquery | Execute a PowerQuery against the Singularity Data Lake | query (required), fromDate, toDate |
get_timestamp_range | Get the available time range for PowerQuery data | None |
iso_to_unix_timestamp | Convert ISO 8601 timestamp to Unix epoch milliseconds | timestamp (required) |
Call powerquery with a query string and optional time range:
Default time range: Last 24 hours if not specified.
Example: Find PowerShell network connections:
powerquery with query="EventType = \"IP Connect\" AND SrcProcName = \"powershell.exe\" | columns EndpointName, SrcProcCmdLine, DstIP, DstPort | limit 100"Example: With custom time range:
powerquery with query="EventType = \"Process Creation\" AND TgtProcName = \"mimikatz.exe\" | limit 50", fromDate="2026-02-23T00:00:00Z", toDate="2026-02-24T00:00:00Z"Call get_timestamp_range to determine how far back the Data Lake has data. Returns the earliest and latest available timestamps.
Call iso_to_unix_timestamp to convert ISO 8601 timestamps to Unix epoch milliseconds, which is required by some query parameters.
PowerQuery uses a pipeline model with filters, columns, sorting, and aggregation:
<filter expression>
| columns <field1>, <field2>, ...
| sort -<field>
| limit <n>
| group <field> calculate count() as cnt
Filters use field operator value syntax:
| Operator | Description | Example |
|---|---|---|
= | Equals | EventType = "Process Creation" |
!= | Not equals | SrcProcName != "explorer.exe" |
contains | Substring match | TgtProcCmdLine contains "powershell" |
In | Match list | DstPort In (80, 443, 8080) |
NOT In | Exclude list | NOT DstIP In ("10.0.0.0/8") |
AND | Logical AND | EventType = "IP Connect" AND DstPort = 4444 |
OR | Logical OR | SrcProcName = "cmd.exe" OR SrcProcName = "powershell.exe" |
| Operator | Description | Example |
|---|---|---|
columns | Select specific fields | | columns EndpointName, SrcProcName, DstIP |
sort | Sort results (prefix - for descending) | | sort -EventTime |
limit | Limit result count (max 100) | | limit 100 |
group | Aggregate data | | group EndpointName calculate count() as cnt |
filter | Post-pipeline filter | | filter cnt > 10 |
| Event Type | Description |
|---|---|
Process Creation | New process started |
Process Exit | Process terminated |
IP Connect | Network connection established |
IP Listen | Port opened for listening |
File Creation | File created |
File Modification | File modified |
File Deletion | File deleted |
Registry Key Creation | Registry key created |
Registry Value Modified | Registry value changed |
DNS | DNS query |
Login | User login event |
Logout | User logout event |
Module Load | DLL or shared library loaded |
URL | URL accessed |
| Field | Description |
|---|---|
EndpointName | Hostname of the endpoint |
SiteName | SentinelOne site (MSP client) |
EventTime | Event timestamp |
EventType | Type of event |
SrcProcName | Source (parent) process name |
SrcProcCmdLine | Source process command line |
SrcProcPid | Source process ID |
TgtProcName | Target (child) process name |
TgtProcCmdLine | Target process command line |
TgtProcPid | Target process ID |
DstIP | Destination IP address |
DstPort | Destination port |
SrcIP | Source IP address |
SrcPort | Source port |
NetConnStatus | Network connection status |
TgtFileName | Target file name/path |
TgtFileHashSha256 | Target file SHA256 hash |
RegistryKeyPath | Registry key path |
RegistryValueName | Registry value name |
DNSRequest | DNS query domain |
URL | Accessed URL |
User | User account |
| Constraint | Value |
|---|---|
| Maximum rows returned | 100 |
| Default time range | Last 24 hours |
| Query timeout | 5 minutes |
| Empty results | Valid (no matching data, not an error) |
EventType = "Process Creation" AND
(TgtProcName = "psexec.exe" OR TgtProcName = "psexesvc.exe" OR
TgtProcCmdLine contains "wmic" AND TgtProcCmdLine contains "/node:")
| columns EndpointName, SiteName, SrcProcName, TgtProcName, TgtProcCmdLine, EventTime
| sort -EventTime
| limit 100
EventType = "Process Creation" AND
TgtProcCmdLine contains "lsass" AND
SrcProcName != "svchost.exe" AND SrcProcName != "csrss.exe"
| columns EndpointName, SiteName, SrcProcName, TgtProcName, TgtProcCmdLine, User, EventTime
| sort -EventTime
| limit 100
EventType = "Process Creation" AND
TgtProcName = "schtasks.exe" AND TgtProcCmdLine contains "/create"
| columns EndpointName, SiteName, SrcProcName, TgtProcCmdLine, User, EventTime
| sort -EventTime
| limit 100
EventType = "IP Connect" AND NetConnStatus = "SUCCESS" AND
NOT DstIP In ("10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16") AND
DstPort NOT In (80, 443)
| group DstIP, SrcProcName, EndpointName calculate count() as connections
| filter connections > 50
| sort -connections
| limit 100
EventType = "Process Creation" AND
(TgtProcName In ("7z.exe", "rar.exe", "zip.exe", "tar.exe") OR
TgtProcCmdLine contains "Compress-Archive")
| columns EndpointName, SiteName, SrcProcName, TgtProcCmdLine, User, EventTime
| sort -EventTime
| limit 100
EventType = "Process Creation" AND
TgtProcName In ("certutil.exe", "mshta.exe", "regsvr32.exe", "rundll32.exe",
"wscript.exe", "cscript.exe", "bitsadmin.exe") AND
(TgtProcCmdLine contains "http" OR TgtProcCmdLine contains "ftp" OR
TgtProcCmdLine contains "/decode" OR TgtProcCmdLine contains "script:")
| columns EndpointName, SiteName, SrcProcName, TgtProcName, TgtProcCmdLine, EventTime
| sort -EventTime
| limit 100
EventType = "DNS" AND
DNSRequest contains "." AND
NOT DNSRequest In ("*.microsoft.com", "*.windows.com", "*.windowsupdate.com",
"*.office.com", "*.sentinelone.net")
| group DNSRequest calculate count() as queries
| filter queries > 100
| sort -queries
| limit 100
EventType = "Process Creation" AND
SrcProcName In ("winword.exe", "excel.exe", "powerpnt.exe") AND
TgtProcName In ("powershell.exe", "cmd.exe", "wscript.exe", "cscript.exe", "mshta.exe")
| columns EndpointName, SiteName, SrcProcName, TgtProcName, TgtProcCmdLine, User, EventTime
| sort -EventTime
| limit 100
The recommended threat hunting workflow is:
purple_ai with a natural language description of what you want to findget_timestamp_range to verify data availabilitypowerquery with the generated query stringPowerQuery Result:
{
"rows": [
{
"EndpointName": "ACME-WS-042",
"SrcProcName": "winword.exe",
"TgtProcName": "powershell.exe",
"TgtProcCmdLine": "powershell.exe -enc aQBlAHgA...",
"EventTime": "2026-02-24T08:12:34.000Z"
},
{
"EndpointName": "ACME-WS-015",
"SrcProcName": "excel.exe",
"TgtProcName": "cmd.exe",
"TgtProcCmdLine": "cmd.exe /c whoami && net user",
"EventTime": "2026-02-24T07:45:12.000Z"
}
],
"totalRows": 2
}
Empty Result (Valid):
{
"rows": [],
"totalRows": 0
}
Empty results are valid and common in threat hunting. No results means no matching telemetry was found -- which is often a positive finding.
| Error | Cause | Resolution |
|---|---|---|
| Syntax error | Invalid PowerQuery syntax | Use purple_ai to generate correct syntax |
| Timeout | Query too broad or time range too large | Narrow the time range or add more filters |
| No data available | Time range outside Data Lake retention | Call get_timestamp_range to check availability |
| Authentication error | Invalid token | Verify Service User token is Account or Site level |
| Rate limited | Too many queries | Wait before retrying |
SrcProcName = "powershell.exe"In (capital I) for list matches: DstPort In (80, 443)NOT before conditions for negation: NOT DstIP In ("10.0.0.0/8")| on a new line or after a space| limit 100 to stay within the row limitSiteName = "Client Name" to scope hunts to specific clients