Description
The Jira integration routes in src/app/api/integrations/jira/route.ts and src/app/api/integrations/jira/credentials/route.ts allow users to set up credentials for their Jira account by specifying a jiraDomain.
During the validation step in /api/integrations/jira/credentials, the validateJiraDomain function checks that the domain ends with .atlassian.net:
function validateJiraDomain(domain: string): boolean {
const domainRegex = /^[a-zA-Z0-9][-a-zA-Z0-9]*\.atlassian\.net$/;
return domainRegex.test(domain);
}
However, this regex checks the format of the domain name but does not prevent the domain name from resolving to loopback or private IP addresses (for example, an attacker can configure a subdomain malicious.atlassian.net in their own DNS server or register it to point to a private IP like 127.0.0.1 or 192.168.1.1).
Furthermore, during the actual issue fetching in src/app/api/integrations/jira/route.ts:
async function fetchJiraIssues(
domain: string,
email: string,
token: string,
projectKey?: string
): Promise<JiraIssue[]> {
...
const searchUrl = `https://${domain}/rest/api/3/search?jql=${encodeURIComponent(
jql
)}&maxResults=50&fields=...`;
const response = await fetch(searchUrl, {
headers,
cache: "no-store",
});
The application executes the fetch request using Basic Authentication (consisting of the user's decrypted Jira API token and email) directly against the user-supplied domain without performing any SSRF checks or validating the resolved IP address using isSafeUrl.
Impact
An attacker can supply a domain like internal.atlassian.net (which resolves to 127.0.0.1 or another internal resource), causing the DevTrack server to send HTTP requests with sensitive authorization credentials to internal services. This leads to credential theft and Server-Side Request Forgery (SSRF).
Affected Files
- credentials/route.ts
- jira/route.ts
Steps to Reproduce
- Create a custom domain under Atlassian's domain or point a DNS record of a sub-domain (e.g.,
ssrf.atlassian.net) to 127.0.0.1.
- Submit this domain to the
/api/integrations/jira/credentials endpoint.
- Observe that the connection test passes (if an HTTP service is running locally on the target port) and the credentials get saved.
- When fetching issues, the server performs a GET request to the local loopback address.
Suggested Solution
Resolve the domain to its IP address and validate it using a robust isSafeUrl check before calling fetch in both testJiraConnection and fetchJiraIssues.
Labels: gssoc, quality:exceptional, level:critical
/assign
Description
The Jira integration routes in
src/app/api/integrations/jira/route.tsandsrc/app/api/integrations/jira/credentials/route.tsallow users to set up credentials for their Jira account by specifying ajiraDomain.During the validation step in
/api/integrations/jira/credentials, thevalidateJiraDomainfunction checks that the domain ends with.atlassian.net:However, this regex checks the format of the domain name but does not prevent the domain name from resolving to loopback or private IP addresses (for example, an attacker can configure a subdomain
malicious.atlassian.netin their own DNS server or register it to point to a private IP like127.0.0.1or192.168.1.1).Furthermore, during the actual issue fetching in
src/app/api/integrations/jira/route.ts:The application executes the
fetchrequest using Basic Authentication (consisting of the user's decrypted Jira API token and email) directly against the user-supplieddomainwithout performing any SSRF checks or validating the resolved IP address usingisSafeUrl.Impact
An attacker can supply a domain like
internal.atlassian.net(which resolves to127.0.0.1or another internal resource), causing the DevTrack server to send HTTP requests with sensitive authorization credentials to internal services. This leads to credential theft and Server-Side Request Forgery (SSRF).Affected Files
Steps to Reproduce
ssrf.atlassian.net) to127.0.0.1./api/integrations/jira/credentialsendpoint.Suggested Solution
Resolve the domain to its IP address and validate it using a robust
isSafeUrlcheck before callingfetchin bothtestJiraConnectionandfetchJiraIssues.Labels: gssoc, quality:exceptional, level:critical
/assign