The package could already write to a unified alert — update its status and
its analyst verdict — but never read one. The only fetch was get_alerts,
which reads /cloud-detection/alerts: a different object, covering only the
detections the STAR and custom rules raise. Everything SentinelOne surfaces
through the console-wide alert model — cloud, identity, third-party — had
no way into an incident.
get_unified_alerts reads the unifiedalerts GraphQL endpoint, alongside the
two mutations already pointed at it. Notes on the shape it returns:
- edges/node is flattened to a plain data[]. The envelope carries no id of
its own, so a rule dedup'ing on a top-level id would key every alert on
nothing; flattened, the ingest block matches the REST commands in this
package (results_path: data, dedup_key: id).
- Sorted ascending, so a run truncated by the limit leaves the watermark on
the oldest unseen alert instead of skipping everything behind the newest.
- created_after is normalised from ISO8601, epoch seconds or epoch
milliseconds: the scheduler injects the watermark raw, in whichever of the
three formats the rule was configured with. The script builds the GraphQL
filter itself, so the incremental input stays a plain timestamp.
- A GraphQL error arrives as HTTP 200 with an errors array. Left unread, an
unusable query would look like an endless run of empty, successful fetches.
The mapper covers 74 fields. Its severity branch ends on the raw value
rather than a number, so an alert with no severity — or a level SentinelOne
adds later — falls through to the rule's default instead of being asserted
Informational on data that never said so. A UAM alert also carries fields
with no honest OCSF home (assignee, ticketId, the kubernetes controllers);
they are fetched and left in the raw payload rather than forced into an
unrelated field.
The package default ingestion still points at get_threats: the new command
is opt-in from the Collect editor, so no existing instance changes what it
collects.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Declared as a boolean, isActive rendered as a checkbox in the toolbox,
and a checkbox has no empty state: the count was forced to one half of
the fleet or the other, with no way to ask for both. As text, an empty
field means the filter is not sent.
true/yes/1 and false/no/0 are read in any case, a real JSON boolean from
a playbook still works, and anything else is refused rather than folded
into false — that would answer a different question than the one asked.
A multi-tenant console answered one number for the whole estate.
accountIds narrows the count to the accounts asked for, the way
get_threats and get_alerts already do at fetch time.
isActive splits a count that until now lumped both together. It is sent
only when the caller sets it: an unset boolean must not reach the console
as isActive=false and quietly count the dormant agents instead of all of
them.
The count only knew where an agent was, not what it was running or what
it runs on. Four filters carry the console's own vocabulary through:
agentVersion__gt to count the fleet still below a target build,
networkStatuses to keep only the endpoints in a given connection state,
operationalStatesNin to leave states out of the tally, and machineTypes
to count servers apart from laptops.
The list filters are split and re-joined so a hand-typed
"connected, disconnected" does not reach the API with the space inside
the value.
A multi-tenant console returns every account's threats and alerts at once.
get_threats and get_alerts now take an optional account_ids input, passed
through as the accountIds query parameter, so an ingestion can be pinned to
the accounts the SOC actually watches.
The input is optional, so existing instances and running ingestions keep
their current behaviour.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Declare get_threats as the default fetch command (results_path data, dedup id,
incremental created_after) with the bundled get_threats OCSF mapper and a
'SentinelOne Threat' default incident type. get_alerts is also marked
ingestion-ready (incremental created_from). Existing filters (mitigation
status, query, created window, limit) let an operator fetch a subset.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Brings the SentinelOne integration to 83 commands. New: threat-analysis,
threat-download-from-cloud, abort-endpoint-scan, endpoint-fetch-logs, fetch-file,
get-remote-script-task-status, get-remote-script-task-results, get-service-users,
list-installed-singularity-marketplace-applications, update-uam-alert-status,
update-uam-alert-verdict, run-powerquery (Singularity Data Lake), create-tag-rule.
Each command ships a stdlib-only script against API v2.1.
Rename every command 'name' in the official integrations to a
<technology>-<command> slug (e.g. sentinelone-isolate-agent,
harfanglab-isolate-endpoint) so they group together when searching the
toolbox. Command IDs (and thus script files and action refs) are unchanged.
Bump both integrations to 1.1.0.
Expand from 9 to 70 commands covering the official + DEV SentinelOne V2
integrations: agents (actions/info/tags/count), threats & alerts (verdict/status/
notes/mitigate/fetch-file), hash blocklist & exclusions, IOCs, STAR rules,
Deep Visibility, remote scripts, endpoint tags, firewall rules and network
discovery. All script-based (urllib, INTEGRATION_SECRETS/INPUTS contract);
inputs prioritized from the DEV integration.