From d48c2c38faca629bf7df26fa8d45e9c3878b6800 Mon Sep 17 00:00:00 2001 From: Ice3man Date: Thu, 18 Dec 2025 22:17:45 +0530 Subject: [PATCH] feat(trackers): add site-url to optionally provide jira server URL for oauth (#6716) * feat: add site-url to optionally provide jira server URL for oauth * chore(cmd): add `site-url` config option Adds optional `site-url` field to JIRA issue tracker configuration for specifying browsable URL when it differs from the API endpoint. This is particularly useful for OAuth-based JIRA Cloud integrations where `issue.Self` contains "api.atlassian.com" instead of the user-facing domain. Signed-off-by: Dwi Siswanto --------- Signed-off-by: Dwi Siswanto Co-authored-by: Dwi Siswanto --- cmd/nuclei/issue-tracker-config.yaml | 3 +++ pkg/reporting/trackers/jira/jira.go | 29 ++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/cmd/nuclei/issue-tracker-config.yaml b/cmd/nuclei/issue-tracker-config.yaml index ef5b8ec2a..7e8acfa63 100644 --- a/cmd/nuclei/issue-tracker-config.yaml +++ b/cmd/nuclei/issue-tracker-config.yaml @@ -100,6 +100,9 @@ # update-existing: false # # URL is the jira application url # url: https://localhost/jira +# # site-url is the browsable URL for the Jira instance (optional) +# # If not provided, issue.Self will be used. Useful for OAuth where issue.Self contains api.atlassian.com +# site-url: https://your-company.atlassian.net # # account-id is the account-id of the Jira user or username in case of on-prem Jira # account-id: test-account-id # # email is the email of the user for Jira instance diff --git a/pkg/reporting/trackers/jira/jira.go b/pkg/reporting/trackers/jira/jira.go index 1fe02b085..2156a354a 100644 --- a/pkg/reporting/trackers/jira/jira.go +++ b/pkg/reporting/trackers/jira/jira.go @@ -184,6 +184,9 @@ type Options struct { UpdateExisting bool `yaml:"update-existing" json:"update_existing"` // URL is the URL of the jira server URL string `yaml:"url" json:"url" validate:"required"` + // SiteURL is the browsable URL for the Jira instance (optional) + // If not provided, issue.Self will be used. Useful for OAuth where issue.Self contains api.atlassian.com + SiteURL string `yaml:"site-url" json:"site_url"` // AccountID is the accountID of the jira user. AccountID string `yaml:"account-id" json:"account_id" validate:"required"` // Email is the email of the user for jira instance @@ -346,16 +349,26 @@ func (i *Integration) CreateNewIssue(event *output.ResultEvent) (*filters.Create } return nil, fmt.Errorf("%w => %s", err, data) } - return getIssueResponseFromJira(createdIssue) + return i.getIssueResponseFromJira(createdIssue) } -func getIssueResponseFromJira(issue *jira.Issue) (*filters.CreateIssueResponse, error) { - parsed, err := url.Parse(issue.Self) - if err != nil { - return nil, err +func (i *Integration) getIssueResponseFromJira(issue *jira.Issue) (*filters.CreateIssueResponse, error) { + var issueURL string + + // Use SiteURL if provided, otherwise fall back to original issue.Self logic + if i.options.SiteURL != "" { + // Use the configured site URL for browsable links (useful for OAuth) + baseURL := strings.TrimRight(i.options.SiteURL, "/") + issueURL = fmt.Sprintf("%s/browse/%s", baseURL, issue.Key) + } else { + // Fall back to original logic using issue.Self + parsed, err := url.Parse(issue.Self) + if err != nil { + return nil, err + } + parsed.Path = fmt.Sprintf("/browse/%s", issue.Key) + issueURL = parsed.String() } - parsed.Path = fmt.Sprintf("/browse/%s", issue.Key) - issueURL := parsed.String() return &filters.CreateIssueResponse{ IssueID: issue.ID, @@ -376,7 +389,7 @@ func (i *Integration) CreateIssue(event *output.ResultEvent) (*filters.CreateIss if err != nil { return nil, errors.Wrap(err, "could not add comment to existing issue") } - return getIssueResponseFromJira(&issue) + return i.getIssueResponseFromJira(&issue) } } resp, err := i.CreateNewIssue(event)