---
title: "Jira"
---

The ((Jira)) integration connects runZero to a Jira Cloud project for issue-tracking and service-desk operations. Once configured, you can push a runZero [issue](docs/issues.md) out to Jira as a ticket and keep the runZero issue timeline in sync with changes made on the Jira side.

> If you are looking for the asset-enrichment integration that imports runZero asset data into Jira Service Management's CMDB, see [Atlassian Insight & Jira Service Management](docs/atlassian-jira-service-management.md) instead. That integration is independent of the issue-tracking sync described here.

## How the integration works

- runZero authenticates to Jira Cloud as a regular Atlassian user using HTTP basic auth (email + API token).
- When you create a Jira ticket from a runZero issue, runZero calls the Jira REST API (v3) to create the issue in the project configured on the credential, copies the relevant fields across, and stores the resulting Jira key and link on the runZero issue.
- A configurable Jira webhook posts changelog events back to runZero, where each change becomes a timeline entry on the matching runZero issue. If [state mapping](#state-mapping-and-bidirectional-sync) is configured, status and due-date changes also update the runZero issue directly.
- When you change a runZero issue state, runZero calls the Jira Transitions API to move the linked ticket to the corresponding Jira status (if a state mapping is configured).
- All traffic is initiated by runZero (outbound to Jira) or signed and verified with HMAC-SHA256 (inbound from Jira). No other Jira data is written to or read from your environment.

## Prerequisites {#jira-prerequisites}

Before you start you need:

- An Atlassian Cloud account that can create issues in the target Jira project.
- A Jira project to write tickets to, and that project's **Project key** (for example `SCRUM`, `SEC`, or `OPS`).
- A Jira API token. Create one at [https://id.atlassian.com/manage-profile/security/api-tokens](https://id.atlassian.com/manage-profile/security/api-tokens) and copy it somewhere safe &mdash; it cannot be viewed again after the dialog is closed.
- A randomly generated **webhook secret** if you plan to enable two-way sync. Any reasonably long random string will do; runZero uses it to verify inbound webhook requests.
- The Jira integration entitlement on your runZero account.

## Creating the Jira credential

The Jira integration uses a runZero [credential](docs/scanning-credentials.md) of type **Jira API Token**. You can create one ahead of time from the Credentials page, or directly from the **Create Jira ticket** dialog the first time you push an issue.

To create the credential ahead of time:

1. Go to [Credentials](https://console.runzero.com/credentials/) in the runZero Console.
2. Click **New credential** and choose **Jira API Token**.
3. Fill in the form:
   - **URL** &mdash; the base URL of your Jira Cloud site, for example `https://yourcompany.atlassian.net`. Do not include a trailing path.
   - **Email** &mdash; the email address of the Atlassian user the API token belongs to. This account must be able to create and transition issues in the target project.
   - **API token** &mdash; the API token you created on the Atlassian side.
   - **Webhook secret** &mdash; a random string used to authenticate inbound Jira webhooks. Save the value somewhere you can paste it into Jira later.
   - **Jira Project Key** &mdash; the key of the Jira project where tickets will be created (for example `SEC` or `OPS`). This is required; ticket creation will fail if the field is left empty.
   - **Map Issue States to Jira Values** &mdash; optional. A table mapping each runZero issue state to the corresponding Jira status name. See [State mapping and bidirectional sync](#state-mapping-and-bidirectional-sync) below for details.
4. Save the credential. runZero validates the URL, email, and token by making an authenticated call to Jira and rejects the credential if the call fails. The validation result is shown next to the credential.

<!-- TODO: Arcade demo — replace with link from https://demo.arcade.software -->

After the credential is saved, open it to edit and you will see a read-only **Jira webhook URL** field. Copy this URL and use it when [configuring the Jira webhook](#configuring-the-jira-webhook).

A single credential can be reused for as many Jira tickets as you like, but if you change the API token in Atlassian you must update the credential in runZero or future calls will fail.

## Creating a Jira ticket from an issue

1. Open an issue from the [Issues page](https://console.runzero.com/issues/).
2. In the sidebar,
  - **Credential** &mdash; select the desired Jira credential.
  - **Attach snapshot to ticket** &mdash; optional. When enabled, runZero uploads a CSV of the issue's instance snapshot as an attachment on the new Jira ticket.
  - Click **Create ticket**.

<!-- TODO: Arcade demo — replace with link from https://demo.arcade.software -->

runZero will:

- Create the Jira issue using the project key from the credential, the summary, description, and the runZero issue's due date if one is set.
- Optionally upload the snapshot CSV as a Jira attachment. CSV upload failures do not abort ticket creation; the ticket is still linked.
- Save the Jira issue key (for example `SEC-42`), a browse link (`{your-jira-url}/browse/SEC-42`), and the credential and Jira base URL on the runZero issue.
- Append a `Created Jira ticket SEC-42 for issue "..."` entry to the runZero issue timeline.

Once linked, the issue sidebar shows the Jira key and a button that opens the ticket in Jira.

A runZero issue can be linked to at most one Jira ticket at a time. If you need to relink, [unlink](#unlinking-a-ticket) the existing one first.

### Unlinking a ticket

From a runZero issue with a linked ticket, use the unlink action in the sidebar to clear the link. Unlinking only affects runZero &mdash; the Jira ticket itself is not deleted or modified. After unlinking you can create a new ticket from the same issue if needed.

## State mapping and bidirectional sync {#state-mapping-and-bidirectional-sync}

<!-- TODO: Arcade demo — replace with link from https://demo.arcade.software -->

The **Map Issue States to Jira Values** table on the Jira credential enables two-way state and due date synchronization between runZero issues and Jira tickets.

To configure state mapping, open the credential and add one row per runZero state you want to sync:

- **Issue State** (key) &mdash; one of the four runZero issue states: `open`, `in progress`, `closed`, or `resolved`.
- **Jira Value** (value) &mdash; the exact name of the corresponding Jira status in your project workflow, for example `To Do`, `In Progress`, or `Done`. Matching is case-insensitive for inbound webhook events.

You can map all four states or only a subset. Unmapped states are ignored in both directions.

### Outbound sync (runZero &rarr; Jira)

When you change a runZero issue state (or when runZero automatically transitions an issue to `resolved`), runZero looks up the new state in the credential's state mapping. If a Jira status name is configured for that state, runZero calls the [Jira Transitions API](https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-issueidorkey-transitions-post) to move the linked ticket to the target status.

If the Jira workflow does not have an available transition to that status from the ticket's current status, the transition silently fails. The runZero state change is always applied regardless of whether the Jira transition succeeds.

### Inbound sync (Jira &rarr; runZero)

When Jira sends a webhook with a status change, runZero reverses the state mapping to find the matching runZero state and updates the issue accordingly. Due date changes on the Jira ticket are also propagated back to the runZero issue.
#### NOTE: The casing of the Jira status needs to match the casing set in the Jira workflow
Example mapping:

| runZero state | Jira status |
|---|---|
| `Open` | `To Do` |
| `In progress` | `In Progress` |
| `Closed` | `Closed` |
| `Resolved` | `Done` |

## Configuring the Jira webhook

To enable inbound sync from Jira back to runZero, configure a Jira webhook for the project (or the whole site):

1. In Jira, go to **System** &rarr; **WebHooks** and click **Create a WebHook** (administrator access required).
2. **Name** &mdash; anything descriptive, for example `runZero issue sync`.
3. **URL** &mdash; open your runZero Jira credential and copy the read-only **Jira webhook URL** field. It follows the pattern `https://<your-runzero-console>/api/webhooks/jira/${issue.key}`. The literal text `${issue.key}` is a Jira URL variable; Jira substitutes it with the actual issue key for each event.
4. **Secret** &mdash; paste the same webhook secret you saved on the runZero credential. Jira will sign each request with HMAC-SHA256 and send the signature in the `X-Hub-Signature` header.
5. **Events** &mdash; enable at least the **issue updated** event. You can add more events; runZero records every changelog item it receives.
6. (Optional) **JQL filter** &mdash; restrict the webhook to the project used with this credential, for example `project = SEC`. This prevents unnecessary events from other projects.
7. Save the webhook.

<!-- TODO: Arcade demo — replace with link from https://demo.arcade.software -->

When an event fires, runZero:

1. Looks up the matching runZero issue by Jira issue key + Jira base URL (so multiple Jira sites do not collide).
2. Validates the HMAC-SHA256 signature against the credential's webhook secret using a constant-time comparison.
3. If [state mapping](#state-mapping-and-bidirectional-sync) is configured, applies any status or due-date changes to the runZero issue.
4. Appends one timeline line per changelog item. The line uses the form:

```
Jira update (SEC-42): status changed from "In Progress" to "Done"; assignee set to "alice@example.com"
```

If a webhook arrives without a valid signature, for an unknown Jira key, or for a runZero issue that has been deleted, runZero silently returns `200 OK` without writing anything &mdash; this prevents the endpoint from leaking which keys are linked.

## What gets sent to Jira

At ticket creation time, runZero sends:

- The runZero issue **name** as the Jira **summary**.
- The runZero issue **description** as the Jira **description**.
- The runZero **due date**, if one is set, as the Jira **due date**.
- The **project key** from the credential, used to route the ticket to the right project.
- Optionally, a CSV file containing one row per (vulnerability, asset) instance from the issue snapshot, uploaded as a Jira attachment.

After ticket creation, ongoing sync depends on your [state mapping](#state-mapping-and-bidirectional-sync) configuration:

- **runZero &rarr; Jira**: state transitions are pushed to Jira via the Transitions API when a runZero issue state changes and a mapping is configured.
- **Jira &rarr; runZero**: status and due date changes arrive via the Jira webhook and are applied to the runZero issue (state mapping required for status changes).

runZero does not push comments, description edits, or other field changes to Jira after the initial ticket creation.

## Troubleshooting

- **Credential verification fails when saving.** Double-check the URL has no trailing path, the email matches the Atlassian account that owns the API token, and the token has not been revoked. The credential page shows the specific HTTP status returned by Jira.
- **Create Jira ticket returns an error.** The runZero issue must have a non-empty name and description. The selected credential must have a **Jira Project Key** configured; if the field is empty the request will fail with a *project_key is required* error. The project key must exist in Jira and the API user must be allowed to create issues in it. The error message echoes the HTTP status returned by Jira.
- **Snapshot CSV is missing from the Jira ticket.** Snapshot upload is best-effort &mdash; the ticket is still created if the upload fails. Check that the API user has permission to add attachments to the project.
- **Jira changes do not appear in the runZero timeline.**
  - Confirm the webhook URL contains the literal `${issue.key}` variable.
  - Confirm the webhook secret in Jira matches the value stored on the runZero credential.
  - Confirm the `X-Hub-Signature` header is being sent by Jira (some proxies strip it).
  - Confirm the runZero issue's stored Jira base URL matches the Jira site sending the webhook. If you migrate Jira sites, unlink and recreate the ticket.
- **State changes are not being pushed to Jira.** Confirm the credential has a state mapping entry for the runZero state that changed, and that the Jira status name matches the exact name in your Jira workflow. The API user must also have permission to transition issues in the project. If the target Jira status is not reachable from the ticket's current status via an available Jira workflow transition, the push will silently fail.
- **Jira status changes are not updating the runZero issue state.** Confirm the Jira status name shown in the webhook event matches the value in the credential's state mapping (matching is case-insensitive). Confirm the webhook secret is correct and that the `X-Hub-Signature` header is reaching runZero.