How to build it in Google SecOps
The first line to ship, what the result has to carry, where the card can live, how it learns the case has moved on, and where the analyst’s decisions go. Written for whoever maintains the integration.
Contents
Before any widget, one string.
When the analysis action succeeds, it writes one line, which the Case Wall shows: “Successfully returned Blue Agent analysis for threat … in Wiz.” That line is the integration’s own, and it reaches every tenant, with a widget or without one. It could say the verdict instead:
That is rule 7 of the checklist, degrade to text, and the first half of step 1. It needs no admin and nothing new from the agent except the data cut-off; without one, the line stops at the time the agent ran. What a line of text can’t carry is the age, which grows while the line stands still. The age is the widget’s job.
The card reads the result of Get Blue Agent Analysis exactly as it arrives today, and says more as the result carries more. Every field below is optional, and each one reaches the analyst as a sentence.
| Field | Added by | What the analyst reads |
|---|---|---|
aiAnalysis.dataCutoffAt | The agent | “data up to 13:14 UTC” |
aiAnalysis.sourcesRead, sourcesNotRead | The agent | What it read, “Wiz Defend cloud telemetry, Cloud audit log”, and “Not read: Network flow logs” |
aiAnalysis.claims | The agent | Each claim, and where to check it: “Check in this case: alert A2”, or “Only in Wiz” |
aiAnalysis.missingEvidence | The agent | When present: “No recommendation.”, and the gap in the agent’s words. Low confidence alone does the same |
aiAnalysis.url | The agent | A link to the analysis in Wiz, in a new tab, https only |
aiAnalysis.revisedFrom | The integration, which keeps the verdict it replaces and the analyst’s decision | “Revised. It said Benign at 13:16 UTC; you overrode it to Malicious at 14:04 UTC.”, and the earlier conclusion |
caseContext.coveredAlerts | The action | “about alert A1” |
caseContext.casePriority | The action | Both ratings, each with its owner, and whether they differ: “Wiz: Low severity · this console: Medium case priority · they differ” |
caseContext.fetchedAt | The action | “Added to this case 13:18 UTC” |
caseContext.alertsAfterCutoff, checkedAt | The check in section 04 | “Outdated by alert A3” beside the verdict, then “Alert A3 happened at 13:57 UTC, 43 min after the newest data the agent used. The agent hasn’t seen it. Case last checked 13:58 UTC.” |
Without the check, the card doesn’t guess: it says “Newer alerts not checked” and “Can’t tell if newer alerts arrived: nothing has checked the case.” Until a check says the verdict stands, it doesn’t draw an all-clear in green. And an alert counts as newer when its events came after the cut-off, the same clock the cut-off is on, not when it joined the case.
The admin decides what goes on screen, so the card has three possible homes, and the integration controls only the last.
- As the ready-made widget for the action. This is where the card is a drop-in. Google’s definition sets its scope to the alert, its height to 400 pixels and its width to half, and admins add it to a playbook’s view. Google’s docs describe these widgets as made by its experts; its content hub shows partners write them too (Stairwell’s integration ships three), and Google verifies and publishes what is contributed. Admins can change only its name, description and conditions.
- As an HTML widget an admin builds. On the case’s Overview tab or in a playbook’s view, it reads the action’s result through placeholders. That is where the prototype puts it: on the case Overview, beside Quick Actions. An admin can switch on Safe HTML, which returns the code “without potentially malicious JavaScript”. The card draws with a script, so built this way it needs Safe HTML off; stripped of its script, it shows one line saying so.
- As an insight the action writes. In basic HTML with no scripts, it shows on the Case Wall with no setup, and in the Insights widget where an admin has placed one. Today’s action writes none.
Google’s revamped case view adds one step: its new default views don’t include custom widgets from the legacy views on their own (Google’s docs), so an admin adds them back. Quick Actions work in both.
Drawing Outdated is easy. Knowing when to say it is the work.
The card reads the result of the step that ran for alert A1. Playbooks are attached to alerts, so when alert A3 joins the case, A1’s result stays as it was unless someone reruns A1’s playbook. Nothing in that result can know about A3. Two routes fit what the integration already has.
- The sync job. The integration already ships a job that, where an admin runs it, keeps Wiz threats and SecOps cases in sync by revisiting the cases that have changed; before it updates a threat in Wiz, it checks the other SecOps cases Wiz links to that threat. It could compare each case’s alerts with the verdict’s cut-off and write the Outdated line as an insight: the Case Wall gets it with no widget installed.
- A step for each new alert. A step in the playbook that runs for A3 re-checks the case and fetches the analysis again, so a revision lands as that step’s result. This is what the prototype shows: the revision on the Case Wall, and on the card after Refresh, which assumes the widget reads the latest result (question 3 in section 06).
The job’s lookup of the other cases Wiz links to a threat is also the start of the check this study didn’t design: evidence that lands in another case, where a card inside one case can’t see it.
An HTML widget displays. Its one documented exception, an approval link, only approves or declines a playbook step that is waiting. So every decision is one of the console’s own action types.
- Accept, Override and Undo are the integration’s actions. They sit on a Quick Actions widget: up to six buttons, on the case view, the alert view or a playbook’s alert view. A setting left blank is asked for when the action runs, which is how Override gets its verdict and its reason. Undo clears the decision here; a comment already synced to Wiz stays there.
- Accept is withdrawn while the verdict is low-confidence or outdated. A condition shows or hides a whole widget, not one button, so this takes two Quick Actions widgets with complementary conditions: one with Accept, one without. Each condition needs something to read: the result’s confidence and reported gap, and for outdated, a mark the freshness check writes, such as a tag on the case.
- The same actions run from the Manual Action dialog. It records the run on the Case Wall.
- Closing the case already tells Wiz something. Where an admin runs the sync job, once every alert that carries a threat is closed, here and in the other cases Wiz links to it, the job updates the threat in Wiz from the case’s close reason or verdict: it ignores a false positive, and resolves the rest as malicious, planned action or inconclusive. No field records whether the analyst agreed with the agent. Accept and Override add that.
Each of these decides how the card is installed, and none can be checked without a tenant. They are printed here rather than guessed.
- Whether Safe HTML is on by default for widgets admins build. The ready-made version runs with it off, like every widget in the content hub.
- Whether a widget redraws by itself when a new result arrives. The prototype assumes it doesn’t, and shows the revision on Refresh.
- Which result a widget reads when the same action has run for two alerts in one case: the first alert’s, or the latest.
- Whether a widget condition can read one field inside the result, such as the confidence. Google’s own definition conditions on the result as a whole.
- What the prompt looks like when a Quick Action asks for a setting.
- Whether a ready-made widget renders in the revamped view’s side drawer at all. The card is drawn for that width because rule 1 demands it, not because it is known to work there.
The card is one HTML file and its definition, in the content hub’s own format, open source under Apache-2.0. To ship it, replace the two widget files in the Wiz integration’s folder; the action, scope, height and default width stay the same. Reusing it for another agent means changing its two names, the action it is bound to, and where it finds the analysis in the result.
The harness runs Google’s widget and the card side by side, the way the console runs a widget: the result substituted into the placeholder, a sandboxed frame of the widget’s height, and the host’s theme message. Every example state has its own link.
The tests cover every result shape Google’s widget reads, the age arithmetic (including the 49 days on Wiz’s launch screenshot), the outdated rule with “not checked” kept apart from “fresh”, low confidence, revisions with the analyst’s decision, escaping and https-only links, and that the card draws no control that could change the case. A separate script checks the widget against the method’s gates, G2 and G3, and runs the study’s earlier checks on Option 0, which fails most of them.