Jira Integration
Connect DryRun Security to Jira using automation middleware for automated ticket creation and deduplication.
Overview
DryRun Security does not have a native Jira integration today, but admins can connect DryRun Security to Jira using an automation middleware tool, either Tines or Zapier. DryRun Security sends a webhook when a finding is detected on a PR scan. The middleware receives the webhook, unpacks the finding details, checks Jira for an existing ticket for that finding, and either creates a new ticket or updates the existing one.
When a PR is scanned and a finding is returned, DryRun Security sends a POST request with a JSON payload containing the event type, timestamp, repository, pull request number, and a finding object with id, severity, category, title, file, line, and description. See the Webhook Integration page for the full payload structure and configuration details.
Prerequisites
- DryRun Security webhook configured (see Webhook Integration)
- A Jira project with API access (Jira API token and project key)
- A Tines or Zapier account
Jira Field Mapping
Map DryRun Security finding fields to Jira ticket fields as follows:
| Jira Field | Value from DryRun |
|---|---|
| Summary | [DryRun] {finding.title} in {finding.file}:{finding.line} |
| Description | Full finding description, repository, PR number, severity, file path, finding ID |
| Labels | dryrun-security, {finding.severity}, {finding.category}, {finding.id} (used for deduplication) |
| Priority | Critical → Highest, High → High, Medium → Medium, Low → Low |
Note: The finding.id label is used as the deduplication key to check whether a ticket already exists.
Tines Workflow
Tines is a security automation platform. Use it to receive DryRun Security webhooks and automate Jira ticket creation with deduplication logic.
- Create a Webhook action in Tines: Add a “Webhook” action as the trigger. Tines will generate a unique URL. Copy this URL and use it as the DryRun Security webhook destination in Settings > Integrations.
-
Add a Filter action: Filter on
event == "new_finding"to ensure the workflow only runs for new findings (not scan completions or resolved findings). -
Search Jira for an existing ticket: Add an HTTP Request action to call the Jira REST API:
GET {JIRA_BASE_URL}/rest/api/3/search ?jql=project={PROJECT_KEY} AND labels="{finding.id}" AND statusCategory != Done Authorization: Basic {base64(email:api_token)}This checks whether a ticket already exists for this specific finding by searching for its unique ID in labels.
-
Add a Branch (condition) action: Check the
issuesarray in the Jira search response:- If
issues.length > 0→ ticket exists → go to Step 5 - If
issues.length == 0→ no ticket → go to Step 6
- If
-
Add a comment to the existing Jira ticket. HTTP Request action:
POST {JIRA_BASE_URL}/rest/api/3/issue/{issues[0].id}/comment Body: { "body": "DryRun Security flagged this finding again on PR #{pull_request} in {repository} at {timestamp}." } -
Create a new Jira ticket. HTTP Request action:
POST {JIRA_BASE_URL}/rest/api/3/issue Body: { "fields": { "project": { "key": "{PROJECT_KEY}" }, "summary": "[DryRun] {finding.title} in {finding.file}:{finding.line}", "description": { "type": "doc", "version": 1, "content": [ { "type": "paragraph", "content": [{ "type": "text", "text": "PR: #{pull_request} | Repository: {repository}" }] }, { "type": "paragraph", "content": [{ "type": "text", "text": "Severity: {finding.severity} | Category: {finding.category}" }] }, { "type": "paragraph", "content": [{ "type": "text", "text": "File: {finding.file}:{finding.line}" }] }, { "type": "paragraph", "content": [{ "type": "text", "text": "Finding ID: {finding.id}" }] }, { "type": "paragraph", "content": [{ "type": "text", "text": "{finding.description}" }] } ] }, "issuetype": { "name": "Bug" }, "labels": ["dryrun-security", "{finding.severity}", "{finding.id}"], "priority": { "name": "{mapped priority}" } } }
Workflow diagram: Webhook → Filter (new_finding) → Search Jira → Branch → [Comment on existing ticket | Create new ticket]
Zapier Workflow
Zapier is a no-code automation platform. Use it to build the same DryRun Security → Jira workflow without writing code.
- Create a new Zap and choose “Webhooks by Zapier” as the trigger: Select “Catch Hook” as the trigger event. Zapier generates a webhook URL. Copy it and configure it as the DryRun Security webhook destination in Settings > Integrations.
- Test the trigger: Use DryRun Security’s Test button in the webhook configuration to send a sample payload. This lets Zapier detect the field structure from the finding payload.
-
Add a Filter step: Insert a “Filter” action and set the condition:
event(exactly)new_finding. This ensures the Zap only continues for new findings. -
Add a “Find Issue” Jira action: Choose the Jira Cloud app and select “Find Issue.” Configure the search using JQL:
project = {PROJECT_KEY} AND labels = "{finding.id}" AND statusCategory != DoneMap
finding.idfrom the DryRun Security payload as the label value. -
Add a “Paths” step (two branches):
-
Path A: Ticket exists (Find Issue returned a result):
- Add a Jira “Add Comment to Issue” action.
- Set the Issue ID from the Find Issue result.
- Comment body:
DryRun Security flagged this finding again on PR #{pull_request} in {repository}.
-
Path B: No ticket (Find Issue returned no result):
- Add a Jira “Create Issue” action.
- Map fields from the DryRun Security payload:
- Summary:
[DryRun] {finding.title} in {finding.file}:{finding.line} - Description:
PR: #{pull_request} | Repository: {repository} | Severity: {finding.severity} | File: {finding.file}:{finding.line} | Finding ID: {finding.id} | {finding.description} - Labels:
dryrun-security, severity value, finding ID - Priority: map from severity
- Issue Type: Bug
- Summary:
-
Path A: Ticket exists (Find Issue returned a result):
- Turn on the Zap: Once all steps are configured and tested, enable the Zap.