> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flashduty.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Trivy Operator Alert Integration

> Send vulnerability, exposed secret and config audit reports from Aqua Trivy Operator to Flashduty On-call through its webhook broadcast.

Trivy Operator, Aqua Security's open-source Kubernetes scanner, stores scan results as report objects in the cluster (vulnerability, exposed secret, config audit, infra assessment, RBAC assessment and others). With webhook broadcast enabled, the operator posts each report object as JSON to a URL whenever it creates or updates the report. Each report object (`metadata.uid`) becomes one Flashduty alert, and the alert severity comes from the finding counts in the report summary.

<div className="hide">
  ## In Flashduty On-call

  ***

  You can obtain an integration push URL in either of the following ways.

  ### Use a dedicated integration

  1. In the Flashduty console, select **Channel** and open a channel
  2. Select **Configuration** → **Integrations** → **Private integration**, then click **Add an integration**
  3. Select **Trivy Operator**, then click **Save**
  4. Open the generated integration card and copy the **Push URL**

  ### Use a shared integration

  1. In the Flashduty console, select **Integration Center → Alert Events**
  2. Select **Trivy Operator** and enter an integration name
  3. Configure the default route and pick a channel. You can add more rules under **Route** after creating it
  4. Click **Save** and copy the generated **Push URL**
</div>

## Configure Trivy Operator

***

You need permission to change the Trivy Operator deployment, and the operator must be able to reach the Flashduty push URL over HTTPS.

<Steps>
  <Step title="Set the webhook broadcast URL">
    When installed with Helm, set `operator.webhookBroadcastURL` to the full Flashduty push URL, including `integration_key`:

    ```bash theme={null}
    helm upgrade --install trivy-operator aqua/trivy-operator \
      --namespace trivy-system --create-namespace \
      --reuse-values \
      --set operator.webhookBroadcastURL="https://api.flashcat.cloud/event/push/alert/trivy-operator?integration_key=<your_integration_key>"
    ```

    Without Helm, set the environment variable `OPERATOR_WEBHOOK_BROADCAST_URL` on the operator deployment. Optionally set `operator.webhookBroadcastTimeout` (request timeout, default `30s`).

    Leave `operator.webhookSendDeletedReports` at its default `false`. When it is on, every message is wrapped in `verb` and `operatorObject` (Flashduty parses this), but the object sent for a deleted report has no identifying fields, so Flashduty ignores those messages.
  </Step>

  <Step title="Turn on auto-close">
    The operator pushes only when a report is created or changes and never sends a "resolved" notification. Flashduty recovers an alert automatically only when the same report is scanned again and its summary has no findings at any severity. A rolling update creates a new ReplicaSet and a new report object, so the alert for the old report does not recover. Turn on [auto-close](/en/on-call/channel/create-edit) in the channel that receives these alerts, start the timer from **Incident triggered**, and set a duration of **7 days**.
  </Step>

  <Step title="Verify">
    Trivy Operator has no test button. After the operator finishes a scan, check Flashduty for an alert for the scanned workload. To trigger one quickly, deploy a workload with an old image (for example `nginx:1.16`).
  </Step>
</Steps>

## Alert Key

***

Flashduty uses the UID of the report object (`metadata.uid` in the request body) as the Alert Key. The operator re-sends the same object when a report changes, the UID stays the same, and the pushes merge into one alert. Different workloads, containers and report types have different UIDs and do not affect each other. When a workload is recreated or a report object is deleted and generated again, it gets a new UID and opens a new alert.

Changes to the report name, image tag, scanner version or summary counts do not change the Alert Key. Requests without `metadata.uid` are rejected. A request body larger than 4 MiB is rejected with a parameter error; the description lists at most the 10 most severe findings, so a large report does not enlarge the alert.

## Status and severity

***

Flashduty maps severity from the counts in `report.summary`:

| Summary | Flashduty severity |
| :- | :- |
| `criticalCount` greater than 0 | Critical |
| `highCount` or `mediumCount` greater than 0 | Warning |
| Only `lowCount` or `unknownCount` greater than 0 | Info |
| All counts are 0 | Recovery (Ok) |

When the same report object is pushed again with all counts at 0, its alert recovers automatically.

Reports without a severity summary (SBOM and compliance reports) and deleted-report messages are acknowledged without creating an alert.

## Labels

***

| Label | Source |
| :- | :- |
| `report_type` | Report `kind`; when absent, inferred from the content as `VulnerabilityReport`, `ExposedSecretReport` or `ConfigAuditReport` |
| `report_name` | Report object name |
| `namespace` | Namespace of the scanned workload |
| `resource_kind` / `resource_name` | Kind and name of the scanned workload |
| `resource` | `resource_kind/resource_name`, used in the alert title |
| `container` | Container name (vulnerability and exposed secret reports) |
| `image` | Image repository and tag |
| `critical_count` / `high_count` / `medium_count` / `low_count` / `unknown_count` | Summary counts |
| `scanner_version` | Scanner version |
| `source` | Always `trivy_operator` |

The description holds the summary counts and the 10 most severe findings. For exposed secrets only the rule ID and file path are listed, never the matched text. View the full report with `kubectl get vulnerabilityreports -n <namespace> -o yaml`.

## Troubleshooting

***

* **No alerts arrive**: confirm `operator.webhookBroadcastURL` took effect (check `OPERATOR_WEBHOOK_BROADCAST_URL` on the operator pod) and that the operator log shows no push errors. The operator does not check the response status and does not retry a failed request
* **An alert does not recover**: the operator sends no "resolved" notification. An alert recovers only when the report is scanned again with an all-zero summary, so turn on channel auto-close for the rest
* **Several alerts for one workload**: each report object (vulnerability, exposed secret, config audit and so on) and each container has its own UID, so each opens its own alert
* **Rejected with "metadata.uid is required"**: the request body is not a Trivy Operator report object

See [Trivy Operator: Webhook integration](https://aquasecurity.github.io/trivy-operator/latest/tutorials/integrations/webhook/) for more.
