Safeguard
Developer Tools•

How do you create a Jira ticket from a CI security finding?

Create a Jira issue from a CI job by calling the Jira Cloud REST API with an API token held as a secret. Steps, field gotchas and guardrails.

Safeguard Security Team
4 min read

Add a CI step that sends a POST request to the Jira Cloud REST endpoint for creating issues, authenticated with an Atlassian account email and an API token stored as a CI secret. Send a project key, an issue type and a summary. Only create a ticket when a finding meets your threshold.

What the API expects

Jira Cloud exposes a create issue operation under /rest/api/3/issue. Atlassian's reference says the content of the issue is defined by the fields object, and that the fields you can set depend on what appears on the project's create screen for that issue type. In practice that means you need to know three things before you write any pipeline code: the project key, the issue type name or id, and which fields your project marks as required.

One detail catches people out. In version 3 of the API, the description field, the environment field and any multi-line custom text fields take Atlassian Document Format, a JSON structure, not a plain string. Single-line custom fields still take a string. If your ticket fails with a validation error on description, this is the usual cause.

Authentication choices

Atlassian documents basic authentication for REST clients using an account email address and an API token, and notes that passwords are deprecated. The same page says basic auth is less secure than other methods and points to OAuth 2.0 (3LO) as the stronger option. For a small internal pipeline, a token belonging to a dedicated service account is a reasonable start. Do not use a personal account token, because the automation then disappears when that person leaves.

Store the token in your CI system's secret store, never in the workflow file. Give the service account permission to create issues in one project only.

A minimal step

In GitHub Actions the step looks like this. The job reads the finding from an earlier step, builds the JSON body and posts it.

- name: Open Jira issue
  if: steps.scan.outputs.high_count != '0'
  env:
    JIRA_USER: ${{ secrets.JIRA_USER }}
    JIRA_TOKEN: ${{ secrets.JIRA_TOKEN }}
    TITLE: ${{ steps.scan.outputs.title }}
  run: |
    curl --fail -u "$JIRA_USER:$JIRA_TOKEN" \
      -H "Content-Type: application/json" \
      -X POST "https://your-site.atlassian.net/rest/api/3/issue" \
      --data @issue.json

Notice that the title goes through an environment variable. Putting a context value straight into the shell script is a known injection risk, covered in our post on script injection in automation workflows.

Decide what deserves a ticket

A ticket per finding floods a backlog. A better rule is one ticket per unit of work, such as one per vulnerable package and fixed version. Include the repository, the affected component, the fixed version if one exists, a link to the scan result and the date. Our guide on turning scan findings into a ticket your team will act on covers the fields in detail, and searching before you create stops duplicates.

Guardrails to add on day one

  • Handle HTTP 429 responses by honouring the Retry-After header. Atlassian documents rate limits and tells apps to back off.
  • Cap the number of tickets one run may create, for example ten.
  • Fail loudly when ticket creation fails, so findings are not silently dropped.
  • Put a label such as created-by-automation on every ticket so people can filter and audit them.

Try it yourself

Click through it at your own pace, or open it full screen.

Click a finding and look at what a ticket would need to carry: component, fixed version and owner.

Safeguard can scan your dependencies and apply policies and gates in CI, and you can try a free scan at gold.safeguard.sh/scan to see what findings look like before wiring up tickets.

Quick check

Do I need a Jira plugin to do this?

No. Creating an issue is a plain HTTPS call to the Jira REST API, so any CI system that can run curl can do it.

Why does my create call return a field validation error?

Usually a required field on the create screen is missing, or description was sent as plain text where Atlassian Document Format is expected.

Should the token belong to a person?

Prefer a dedicated service account with access to one project, so the automation survives staff changes and has limited reach.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.