Draft: Pin Jira API requests to the configured host and context path
What does this MR do and why?
Gitlab::Jira::HttpClient forwarded whatever absolute URL jira-ruby derived from the self field of Jira API responses. Jira builds that field from its own base URL, so when the Jira API URL setting points at a different host than the Web URL, sub-resource calls such as remote link creation were addressed to the wrong host.
HTTParty 0.24 added strict base_uri host validation (CVE-2025-68696), so those requests now raise HTTParty::UnsafeURIError instead of being sent. Integrations::Jira#jira_request rescues StandardError, so the cross-reference fails silently — no comment and no remote link are created.
The defect predates the httparty patch. Before it, the mismatched absolute URL was followed, which sent the configured Jira credentials to a host the admin never configured for API traffic.
Why it surfaced when it did
Two changes combine, which is worth knowing when dating the regression:
-
httparty
0.23.1 → 0.24.2reached production on 2026-01-23.issue.remotelink.allstarted raising, butfind_remote_linkwrapped it in its own innerjira_request, so the error was swallowed locally and the lookup just returned nil. The flow continued and both the comment and the remote link still posted over relative paths — only the duplicate-link guard went inert. -
The fix for the duplicate-comment bug unwrapped that call on purpose, so a failed lookup fails closed rather than reading as "no link exists" and duplicating:
def find_remote_link(issue, url) - path = API_ENDPOINTS[:link_remote_issue] % issue.id - links = jira_request(path) { issue.remotelink.all } + links = issue.remotelink.all return unless linksHTTParty::UnsafeURIErrordescends fromStandardError, so that innerjira_requesthad been rescuing it. The error now reaches the outerjira_requestinsend_messageand aborts the whole operation. This reached production on 2026-07-28.
Step 2 is correct behaviour and is not what needs changing — it converted a latent bug into a visible one. This MR removes the cause so the lookup succeeds.
normalize_path now discards everything before the /rest/ prefix and re-anchors the path on the configured context_path. Every request, and the credentials on it, therefore stays on the host and context path the admin configured. The httparty host check stays fully enabled; it is simply no longer handed a mismatched URL.
Jira reports its own context path in self as well, which is not necessarily the context path of the configured API URL. Re-anchoring on the configured value also keeps all calls for one resource consistent — previously the remote link GET and POST could resolve to two different paths for the same resource.
Verification
Both new specs fail on master with the reported HTTParty::UnsafeURIError and pass here:
spec/lib/gitlab/jira/http_client_spec.rbcovers path normalisation directly: differing host, differing context path, matching context path, a context path that itself contains/rest(both guarding against a repeated prefix), query string preservation, and paths with no REST prefix.spec/models/integrations/jira_spec.rbadds an end-to-end regression case driving#create_cross_reference_notewith Jira reporting the Web URL host inself.
Also run green: the full Jira model and client specs with FOSS_ONLY=1, plus the Jira request, import, and vulnerability external link specs.
References
- Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/607785
- Commit:
84d000e53f9 - httparty bump that introduced the host check: !208347 (merged)
- Fail-closed change that made it user-visible: !244579 (merged)
- httparty advisory: https://github.com/jnunemaker/httparty/security/advisories/GHSA-hm5p-x4rq-38w4
- httparty fix: https://github.com/jnunemaker/httparty/commit/0529bcd6309c9fd9bfdd50ae211843b10054c240