rapid7-insightidr 1.14.1: mark UBA alerts in the data, give Static a budget

list_investigation_alerts now marks each alert with alert_rrn, evidence_api
and next: a behaviour alert with no RRN says, in the output the agent reads,
that the Alert Triage commands answer 404 for it and that its evidence is in
the authentication logs. Static still called them when only its instructions
said so. Its sheet gets 14 calls spent in a stated order, authentication log
sets for lateral-movement alerts (never file access), and a window built from
first and last seen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015RhL2gy6Sx6Y3FEsyBE3mZ
This commit is contained in:
2026-10-11 22:20:58 +00:00
parent c5da537434
commit c3b15d1faf
3 changed files with 61 additions and 28 deletions
@@ -38,9 +38,37 @@ def run():
if not all_results:
limit = int(inp.get("limit") or 50)
data = data[:limit]
for a in data:
_annotate(a)
print(json.dumps({"rrn": inv_id, "alert": data}))
def _annotate(a):
"""Say, on each alert, whether the Alert Triage commands can read it.
An investigation's alert list mixes two kinds. A detection-rule alert carries
an RRN (rrn:alerts:...) and answers get_alert_actors / get_alert_evidence. A
behaviour (UBA) alert — "attempted to remotely access N new assets" — has a
plain UUID and no RRN, and those commands answer 404 for it. An agent told so
in its instructions still called them; told so in the data it is reading, it
does not. The hint names where the evidence of such an alert lives instead.
"""
rrn = None
for v in (a.get("rrn"), a.get("id")):
if isinstance(v, str) and v.startswith("rrn:alerts:"):
rrn = v
break
a["alert_rrn"] = rrn
a["evidence_api"] = rrn is not None
if rrn:
a["next"] = "Call get_alert_actors and get_alert_evidence with alert_rrn."
else:
a["next"] = ("Behaviour (UBA) alert with no RRN: get_alert, get_alert_actors, get_alert_evidence and "
"get_alert_process_trees answer 404 for it — do not call them. Its evidence is in the "
"authentication logs: list_log_sets, then query_log_set on the Asset Authentication log set "
"(or each Active Directory one) with where(\"<user>\") over the alert's window.")
try:
run()
except urllib.error.HTTPError as e: