Skip to content
Notifications
Clear all

Has anyone integrated Semgrep with Jira for ticket creation?

18 Posts
18 Users
0 Reactions
211 Views
(@annak8)
Estimable Member
Joined: 4 months ago
Posts: 202
Topic starter   [#26523]

Hey everyone! I've been diving deep into integrating our various security and dev tools into our workflow, and I keep coming back to the same question: can we make security findings actionable and trackable without leaving our existing project management loop? We're heavy Jira users for everything from bug tracking to feature development, so it's the natural place for us.

I've been experimenting with Semgrep's CI integration and the output formats (SARIF, JSON), and I'm now trying to figure out the best way to bridge the gap from a scan result to a created Jira ticket. I know Semgrep App has some native integrations, but our team is currently on the open-source CLI version, and we have some specific requirements for how we want to triage and assign issues.

I'd love to hear from anyone who has actually set this up. My main questions are:

* **Workflow Trigger:** Are you creating tickets directly from the CI pipeline on every scan, or are you using a separate reporting step (maybe a nightly cron job that aggregates findings)?
* **Orchestration Tool:** Did you write a custom script (Python, Bash), use a pre-built GitHub Action or GitLab CI template, or perhaps leverage a third-party middleware like Zapier or a custom webhook listener?
* **Ticket Details:** How do you map the Semgrep results to useful Jira fields? I'm particularly curious about:
* Populating the summary and description with the rule title, finding details, and code snippet.
* Setting the issue type (e.g., "Bug," "Security," "Task").
* Assigning priority based on Semgrep severity (`ERROR`, `WARNING`, etc.).
* Adding labels for the language, framework, or rule ID.
* Linking to the exact file path and line number in the repository.
* **Deduplication & State Management:** This is the big one for me. How do you avoid creating duplicate tickets for the same finding in the same branch? And if a finding is fixed and no longer appears in a scan, do you have a way to automatically resolve or comment on the linked ticket?

I'm imagining a setup where we only create tickets for new `ERROR`-level findings on the main branch after a merge request is completed, but I'm worried about the scripting complexity. The feature matrix nerd in me wants to build a comparison table of all the possible integration methods! Any real-world experiences, gotchas, or even snippets of how you structured your integration logic would be incredibly helpful.

Happy evaluating,
annak8



   
Quote
(@chrisw)
Reputable Member
Joined: 4 months ago
Posts: 322
 

Yeah, we do this. Script in CI on PR merge, not on every scan.

We filter findings first. Noise from mainline scans floods tickets. Script takes semgrep JSON output, uses Jira's REST API.

Key gotcha: deduplication. You need to hash the finding data (rule ID, path, line) and check if a ticket already exists. Otherwise you'll create duplicates on every run. We store the hash in a custom Jira field for lookup.


metrics not myths


   
ReplyQuote
(@hannahw)
Reputable Member
Joined: 4 months ago
Posts: 234
 

Yeah, we ran into the same debate about triggering tickets. Running it in CI on every scan was way too noisy for us.

We settled on a separate nightly reporting step that aggregates findings from the main branch only. The trick is deciding what's "new" each run. We tag issues by rule ID + file path hash, then check for an existing Jira ticket with that tag before creating.

If you want to use a pre-built action, there's a community GitHub Action for Semgrep-to-Jira that's decent as a starting point. We modified it heavily for our triage rules though. Might save you a few hours!



   
ReplyQuote
(@ericd)
Prominent Member
Joined: 4 months ago
Posts: 776
 

That nightly cadence is a solid approach for reducing noise. We tried something similar but found it delayed critical fixes too much. Our compromise was a scheduled scan on the main branch with severity-based filters: only critical and high findings auto-create tickets, everything else goes into a weekly digest report for the security team to review. It keeps the ticket volume manageable while ensuring the urgent stuff gets tracked immediately.


Keep it civil, keep it real.


   
ReplyQuote
(@benchmark_basher)
Reputable Member
Joined: 6 months ago
Posts: 312
 

Severity filters sound good on paper, but have you validated they actually match real risk? Semgrep's own severity tags are often inconsistent across rule packs.

I tested this. Setting it to critical/high gave us tickets for minor config issues while missing some genuine credential exposure patterns marked as medium. You end up gaming the system by re-tagging rules locally, which then breaks on rule updates.

Better to filter by rule ID from a curated list you actually care about, not the vendor's severity. The noise reduction is the same, but the tickets are actually relevant.


-- bb


   
ReplyQuote
(@crm_hopper_alt)
Reputable Member
Joined: 5 months ago
Posts: 357
 

Nightly is better than CI spam, but you're still creating tickets for code that might get fixed before the next morning. Seen it happen.

That community action you mentioned is a mess, honestly. Last I checked, it didn't handle Jira's rate limits, so if you have a big batch of findings it just dies halfway through. You're right to modify it heavily.

The real question is what your ticket state flow looks like after creation. If devs close the ticket in Jira but your script re-opens it the next night because the hash matches, you've just created a fresh hell.


been there, migrated that


   
ReplyQuote
(@crm_trailblazer_7)
Honorable Member
Joined: 7 months ago
Posts: 433
 

The CI trigger is the wrong starting point. You need to define your triage and assignment logic first, because that determines the workflow.

We wrote a Python service that consumes the JSON output. It uses a mapping file we maintain that pairs specific Semgrep rule IDs to Jira project, component, and assignee. This lets us route infrastructure findings to the platform team and app logic issues to the product squad.

Your biggest hurdle won't be the API call to create the ticket. It's managing the lifecycle. Our service checks for a "Resolved" or "Closed" status on any existing ticket with the finding hash before taking action. This prevents the nightly script from re-opening tickets developers already fixed.


Show me the query.


   
ReplyQuote
(@consulting_contractor_mike)
Honorable Member
Joined: 7 months ago
Posts: 393
 

You're asking the right foundational questions about trigger and orchestration. Based on my work across several client environments, the direct CI pipeline trigger is almost always a mistake unless you've already invested heavily in a sophisticated ruleset and path-based filtering. The noise it generates leads to immediate alert fatigue, and developers will start ignoring the Jira project entirely.

A separate, aggregated reporting step is the pragmatic path. The nuance is whether that's a nightly job or a gate on merge to your main/production branch. I've implemented both; the latter often works better because it ties the finding to a discrete change event. A nightly scan of a static main branch loses that crucial context of "what commit introduced this."

Regarding orchestration, I recommend writing a thin, purpose-built service in Python or Go. Pre-built actions tend to be too generic. Your script needs to handle three things well: mapping rule IDs to your internal teams (security vs. platform vs. app dev), intelligent deduplication as others noted, and respecting Jira's API rate limits with exponential backoff. Start with the lifecycle logic user318 mentioned - decide how a ticket transitions from 'new' to 'won't fix' or 'false positive' in your workflow - before you write the first API call. Otherwise, you'll build a ticket generator, not a management system.


Mike


   
ReplyQuote
(@carlam)
Reputable Member
Joined: 4 months ago
Posts: 234
 

Those are the exact same questions we started with. I agree with the folks saying the CI trigger is too noisy, but our team also felt nightly was too slow for high-severity stuff.

We ended up with a hybrid approach using a scheduled job that runs every four hours on the main branch. It's not real-time, but it's fast enough for urgent issues without flooding the queue. The script is a modified version of that community GitHub Action, and yeah, we had to add rate limiting and pagination logic for the Jira API calls - it's a must.

Have you looked at using the SARIF output instead of JSON for this? It structures the data a bit differently and might simplify your mapping logic, especially for linking to the exact line of code.


Benchmarking my way to better decisions


   
ReplyQuote
(@brianw5)
Reputable Member
Joined: 4 months ago
Posts: 276
 

The hybrid scheduled job every few hours is a really smart middle ground! We tried that too but kept it to business hours only (9am/1pm/5pm) to avoid waking people up with ticket storms for issues they couldn't act on overnight. That cut down on the "urgency theater" feeling.

> Have you looked at using the SARIF output instead of JSON for this?

We did evaluate SARIF! It does have better structured locations and a clearer taxonomy. For Jira integration though, we actually went *back* to JSON because the Jira REST API expects a flat structure for the issue fields, and our script was already built around that. The extra nesting in SARIF just meant more transformation work for us. If you're using a system built for SARIF natively (like some security dashboards), it's definitely the better choice.

One thing SARIF helped with, which we kept, was the rule metadata object. We now embed the rule's full description and CWE tags (when available) into the Jira ticket description automatically, which has cut down on triage time.


Automate all the things.


   
ReplyQuote
(@chrisw2)
Reputable Member
Joined: 4 months ago
Posts: 309
 

We went the custom Python script route, triggered from a scheduled job after merge to main. CI was a non-starter for the noise reasons everyone mentioned.

You've got the right instinct about triage logic first. The Jira API call is trivial. Managing the state is the hard part. We hash the rule ID + file path + line number to create a unique key, and store that as a label on the Jira ticket. The script checks if a ticket with that label already exists and is *not* closed before creating a new one. Prevents the dreaded re-open loop.

For output, JSON was simpler for us too. SARIF added complexity we didn't need.


Run it yourself.


   
ReplyQuote
(@integration_ian_3)
Honorable Member
Joined: 5 months ago
Posts: 411
 

Hashing rule ID + path + line is exactly the right approach, we do the same. My one caveat is that line numbers can shift slightly with whitespace changes, which can cause duplicate tickets for what's essentially the same finding.

We tweaked our hash to use the rule ID + file path + the *starting line of the code block* (the `startline` from Semgrep's JSON) instead of the exact line, which gave us a bit more stability. It's a small adjustment but cut down on some false-positives in our duplicate detection.

Also, storing that hash as a label is clever! We use a custom field to keep the labels free for teams, but same principle. The important part is the pre-check against Jira's actual state, which you nailed.


Integration Ian


   
ReplyQuote
(@datadog_dave)
Honorable Member
Joined: 6 months ago
Posts: 494
 

Hey! We've been running this setup for about six months, triggered from a nightly cron job. The CI route was way too noisy for us - devs started muting the Jira project after a week of spam.

We went with a custom Python script that ingests the JSON output. The key, like others mentioned, is that hash for deduplication. We use `rule_id + file_path + startline` and store it in a custom Jira field. Our script checks for existing tickets with that hash and only creates a new one if there isn't an open one already.

One extra thing we added: our script also posts a comment on any existing, *closed* ticket with the same hash, just to let the assignee know the finding has resurfaced. It's been a nice way to avoid re-opening tickets but still keep folks in the loop.


Dashboards or it didn't happen.


   
ReplyQuote
(@harperj)
Honorable Member
Joined: 4 months ago
Posts: 610
 

You're asking the right foundational questions. The thread's covered a lot of ground on triggers and deduplication, which is where the real challenge lies.

One point I haven't seen stressed enough is *ruleset maturity*. Don't build an integration that pipes every single Semgrep rule into Jira right away. Start with a small, high-confidence ruleset - maybe just a dozen rules you've validated produce true positives that are actually actionable for your teams. This solves for both the CI spam problem and the "re-opening hell" scenario, because you're only creating tickets for things you genuinely want tracked. You can expand the list as your triage logic and team tolerance for volume improves.

Your workflow trigger depends entirely on that ruleset and your team's response capacity. If your starting set is small and critical, a CI trigger might be fine. If it's larger or needs manual review, a scheduled job is safer.


Keep it constructive.


   
ReplyQuote
(@andrewh)
Reputable Member
Joined: 4 months ago
Posts: 363
 

That's a great point about line number shifts causing duplicates. I hadn't considered how something as simple as a whitespace change could break the hash. Using the `startline` for the whole code block seems way more stable.

A follow-up question for you: do you ever run into issues where a rule triggers on a *different* code block within the same file, but the startline happens to be the same by coincidence? I'm wondering if we need to include a snippet of the code in the hash, but that feels messy.



   
ReplyQuote
Page 1 / 2