Skip to content

Jira webhook: stop mis-mitigating findings on non-"done" issues#14716

Merged
mtesauro merged 4 commits intoDefectDojo:devfrom
paulOsinski:jira-racecondition
May 1, 2026
Merged

Jira webhook: stop mis-mitigating findings on non-"done" issues#14716
mtesauro merged 4 commits intoDefectDojo:devfrom
paulOsinski:jira-racecondition

Conversation

@paulOsinski
Copy link
Copy Markdown
Contributor

@paulOsinski paulOsinski commented Apr 21, 2026

users see findings auto-mitigated immediately after reopening via
either the UI or API. Looking at finding pghistory we see the pattern:

12:32:48 active=True is_mitigated=False source=None ← user reopens
12:32:51 active=False is_mitigated=True source=jira_webhook ← ricochet

mitigated_by is always the system "JIRA" user, set only from one place:
process_resolution_from_jira's "Mitigated by default" branch.

Root cause

Two independent issues compound:

  1. Self-inflicted race in update_jira_issue. When DefectDojo
    pushes an update to a linked Jira issue, it does
    issue.update(...) first (priority, description, labels) and then
    push_status_to_jira(...) (the transition). Each API call fires its
    own jira:issue_updated webhook. The first webhook, fired by
    issue.update, sees the pre-transition state - for a reopen, that
    means the issue is still resolved from the previous close. Our
    webhook handler then mitigates the linked finding. The second
    webhook, post-transition, would try to reopen the finding, but for
    grouped findings that reopen is (deliberately) gated behind
    DD_JIRA_WEBHOOK_ALLOW_FINDING_GROUP_REOPEN=False, so the ricochet
    is irreversible.

  2. Fragile "resolved" check in the webhook handler. The handler
    treated any non-null resolution as "the Jira issue is closed",
    which also mis-fires for Jira configurations that set a default
    resolution on open issues ("Unresolved"), or workflows whose Reopen
    transition does not clear the resolution field.

Fix

  1. Reorder update_jira_issue so the status transition runs before
    other field updates. Webhooks fired during our own sync now see a
    consistent post-transition state.
  2. In process_resolution_from_jira, require both resolution AND
    statusCategory.key == "done" before mitigating. Extract the
    statusCategory from the webhook payload in webhook() and pass it
    through.

Tests

Three new tests covering status categories new, indeterminate, and
done, all with a non-null resolution value - regression-locking the
guard against the "open but resolved" state.

Backward compatibility

status_category_key is a keyword-only optional argument on
process_resolution_from_jira. When not supplied, behavior is
identical to before the change.

The two PRs address mirror-image failure modes of the same underlying problem (resolution is an unreliable signal; statusCategory is canonical):

The two PRs touch disjoint functions in helper.py and should merge without conflict in either order. Neither subsumes the other: #14611 alone leaves the webhook ricochet in this PR's summary intact; this PR alone leaves the "Jira hides resolution field" setups in #14347 still broken.

@paulOsinski paulOsinski changed the base branch from master to bugfix April 21, 2026 20:08
Copy link
Copy Markdown
Member

@valentijnscholten valentijnscholten left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sesnse. Can you look at #14611? I think the statusCategory itself could be used to determine the state, even if there is no resolution.

Comment thread dojo/jira_link/helper.py Outdated
@paulOsinski
Copy link
Copy Markdown
Contributor Author

@valentijnscholten to fix ruff:

  • dropped the backward-compat if status_category_key is None branch entirely
  • updated the only other caller of process_resolution_from_jira (the jira_status_reconciliation management command) to extract and pass status_category_key alongside the resolution fields, so every caller is on the statusCategory-based path

Copy link
Copy Markdown
Member

@valentijnscholten valentijnscholten left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@paulOsinski @Maffooch It's OK, but should this be combined with #14743 in dev to reduce the chances of errors during conflict resolution? The change from resolution to statusCategory is also more than just a bugfix.

@Maffooch
Copy link
Copy Markdown
Contributor

I'm good with holding it a week to ensure everything rolls out with conflict issue

@Maffooch Maffooch added this to the 2.58.0 milestone Apr 27, 2026
@Maffooch Maffooch force-pushed the jira-racecondition branch from 5e3e0c2 to 62cc0fd Compare April 29, 2026 16:31
@Maffooch Maffooch changed the base branch from bugfix to dev April 29, 2026 16:31
@Maffooch
Copy link
Copy Markdown
Contributor

Rebased onto dev. Resolved the dojo/jira_link/dojo/jira/ move from #14743; logic and tests are unchanged from the original PR (git rename detection mapped both files cleanly, applied hunks identical to the bugfix-based diff). Also forwarded the new status_category_key kwarg through the (currently unused) dojo/jira/services.py wrapper for consistency with the new services layer.

Commit history:

  • 7ccd603 fix jira bug — @paulOsinski
  • 9cd9f2d Update dojo/jira_link/helper.py — @paulOsinski
  • 08b9a60 fix ruff — @paulOsinski
  • 62cc0fd chore: forward status_category_key through jira services wrapper

@github-actions github-actions Bot added the helm label Apr 29, 2026
Copy link
Copy Markdown
Contributor

@mtesauro mtesauro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved

@github-actions github-actions Bot removed the helm label Apr 30, 2026
@paulOsinski
Copy link
Copy Markdown
Contributor Author

Force push was to drop an unnecessary helm-chart related commit. This PR doesn't affect Helm charts at all and the test is likely failing due to a rebase.

@Maffooch Maffooch requested a review from Jino-T April 30, 2026 18:03
@mtesauro mtesauro merged commit 8348cb6 into DefectDojo:dev May 1, 2026
310 of 312 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants