> ## 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.

# JFrog Xray alert integration

> Send the security, license and operational risk violations found by JFrog Xray watches to Flashduty On-call through an Xray webhook.

When a JFrog Xray watch scans a repository, build or release bundle and finds an issue that violates a policy rule, the rule's **Trigger webhook** action sends the violation as JSON to a URL you choose. Point the webhook at the Flashduty push URL and every webhook delivery creates one alert in Flashduty.

Xray sends a webhook only when a scan finds violations and sends nothing when an issue is fixed, so the alert in Flashduty does not recover on its own. Turn on auto-close as described in [Recovery and auto-close](#recovery-and-auto-close).

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

  ***

  You can get the 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 **JFrog Xray** and click **Save**
  4. Open the new integration card and copy the **Push URL**

  ### Use a shared integration

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

## Configure JFrog Xray

***

<Steps>
  <Step title="Create a webhook">
    1. Sign in to the JFrog Platform as an administrator, go to **Administration → Xray Settings → Webhooks** and click **New Webhook**
    2. In **Webhook Name**, enter a name such as `flashduty`; policy rules refer to the webhook by this name
    3. In **URL**, paste the full Flashduty push URL (starting with `https://` and including `integration_key`)
    4. Leave **Use Proxy**, **Basic Auth** and **Custom Headers** empty and click **Create**
  </Step>

  <Step title="Trigger the webhook from a policy rule">
    1. Go to **Platform → Xray → Watches & Policies → Policies** and open an existing policy, or click **New Policy** (type Security, License or Operational Risk)
    2. Edit or create a rule. Under **Then → Do the following actions**, select **Trigger webhook**, choose the webhook from the previous step and click **Save Rule**
    3. Click **Save Policy**. Select the webhook on every rule you want to send to Flashduty
  </Step>

  <Step title="Assign the policy to a watch">
    1. Go to **Platform → Xray → Watches & Policies → Watches** and open an existing watch, or click **New Watch**
    2. Add the repositories, builds or release bundles to scan, add the policy from the previous step and save
  </Step>

  <Step title="Verify">
    The Xray webhook page has no test button. Upload a component with a known vulnerability (for example `log4j-core` 2.14.1) to a watched repository. After Xray scans it, Flashduty shows an alert titled like `JFrog Xray: 7 violations in watch <watch name> (<policy name>)`.
  </Step>
</Steps>

## Recovery and auto-close

***

The Xray violation webhook is sent only when a scan finds violations. The request body has no field that marks a violation as fixed or ignored, so the alert in Flashduty does not recover on its own.

Each delivery is a separate Flashduty alert. Close it by hand, or turn on [auto-close](/en/on-call/channel/create-edit) in the channel that receives this integration, set to how quickly your team handles vulnerabilities, for example 7 days.

## Alert Key

***

Xray creates an `alert_id` for each scan of a watch. When one scan matches several policy rules (for example a security policy and a license policy on the same watch), Xray sends one webhook per rule, all with the same `alert_id`. So Flashduty builds the Alert Key from `alert_id`, the watch name `watch_name`, the policy name `policy_name` and the rule name `policy_rule` (joined with an invisible separator, then MD5):

* A repeated delivery of the same webhook merges into the same alert
* Different rules of one scan, and the next scan (even if it finds the same issues), are different alerts
* Request bodies from older Xray versions have no `alert_id`; Flashduty then generates a random Alert Key and each delivery is its own alert
* If the body has no `watch_name`, Flashduty returns 400 and names the missing field

## Status and severity

***

The alert status equals its severity; it does not recover. The severity comes from the highest severity in the body, `top_severity`; if it is missing or not one of the values below, the most severe issue decides.

| Xray severity | Flashduty severity |
| :- | :- |
| `Critical`, `High` | Critical |
| `Medium` | Warning |
| `Low`, `Information`, `Unknown`, missing or any other value | Info |

## Alert content

***

One webhook holds every issue (`issues`) that the scan found under that rule.

* **Title**: `JFrog Xray: <issue count> violations in watch <watch name> (<policy name>)`; with a single issue, `JFrog Xray: <CVE ID or license name> in <impacted component> (watch <watch name>)`
* **Description**: the watch name, issue count, policy and rule, then the 10 most severe issues (severity, CVE, Xray ID, issue type, impacted component and summary); the remaining issues are only counted

| Label | Source |
| :- | :- |
| `source` | Always `jfrog_xray` |
| `alert_id` | The `alert_id` of the scan |
| `watch_name` / `policy_name` / `policy_rule` | Watch, policy and rule names |
| `top_severity` | Highest severity in the delivery |
| `issue_count` | Number of issues |
| `issue_types` | Issue types, for example `security`, `License` |
| `cves` | CVE IDs involved, most severe first, up to 20 |
| `artifacts` | Impacted components, most severe first, up to 20 |

## Troubleshooting

***

* **Flashduty receives nothing**: check that the policy rule's **Then** section has **Trigger webhook** selected with this webhook, that the policy is assigned to a watch, and that the watch is active. Xray sends a webhook only for newly found violations; saving a rule does not resend violations that already exist. **Apply on Existing Content** in the row actions of the watch does not resend them either. Upload a new vulnerable component to a watched repository to verify
* **Flashduty returns a parameter error**: the body is not JSON, or it has no `watch_name`. Send the Xray violation webhook directly, not through a relay that rewrites the body
* **One scan created several alerts**: Xray sends one webhook for each matched policy rule on the watch, and each becomes its own alert
* **The alert never closes**: Xray sends no recovery notification. Turn on auto-close in the channel, or close the alert by hand

For more details, see the JFrog documentation [Xray Webhooks](https://docs.jfrog.com/security/docs/webhooks).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.