Skip to content

[SECURITY] SSRF Vulnerability in Jira Integration Setup #3119

Description

@basantnema31

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

  1. 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.
  2. Submit this domain to the /api/integrations/jira/credentials endpoint.
  3. Observe that the connection test passes (if an HTTP service is running locally on the target port) and the credentials get saved.
  4. 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

Metadata

Metadata

Labels

gssoc:assignedGSSoC: Issue assigned to a contributor

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions