The GET Request That Reads Your Database Password: Atlassian CVE-2026-21589

An unauthenticated attacker who can reach your Confluence login page can read the file that stores your database password—no credentials, no phishing, no clicks required. That's CVE-2026-21589, and arbitrary file read is the bug…

An unauthenticated attacker who can reach your Confluence login page can, with the right request, read the file that stores your database password. No credentials. No phishing. No clicks. A request and some patience.

That’s the shape of CVE-2026-21589, disclosed by watchTowr Labs against Atlassian products — Jira and Confluence among them, plus additional Atlassian products named in the disclosure. Pre-authentication arbitrary file read. The least glamorous bug class there is, and the one that quietly ends up in the worst breach write-ups because “read any file on the box” includes the files that contain every secret you were careful about everywhere else.

A few honest caveats before the checklist, because the vendor spin cycle hasn’t finished yet. I’m not going to print patch version numbers or release dates I can’t verify against Atlassian’s own advisory — those get corrected after press and you end up chasing a build that doesn’t exist at 2 a.m. I’ve seen no evidence of mass exploitation as of this writing, and I’m not going to invent any. One more thing: arbitrary file read targets the files on a host you run, so this is fundamentally about the instances you host and patch. Confirm the exact affected deployment types — the product lines and whether it’s Server, Data Center or both — against Atlassian’s advisory when it lands, rather than taking my word or a news aggregator’s for which of your boxes are in scope. Here’s the order I’d work it.

1. Find every Atlassian box you actually run — including the ones nobody admits to

The dangerous Confluence instance is never the one in the asset inventory. It’s the one a team stood up on a spare VM in 2021 to “try something,” pointed a DNS record at, and forgot. Pre-auth file read doesn’t care whether you remember it exists.

Start with what answers on the network. Atlassian products tend to leak their version on the unauthenticated login page — in the page footer or embedded markup — without a login, which is convenient for you and for everyone else. The exact markup varies by product and version, so don’t hardcode one pattern and trust it; pull the page, grep for version-looking strings, and confirm against the host. Feed it a list of URLs and let it report:

audit.ps1PowerShell
# Dry-run: fingerprint Atlassian versions from the unauth login page.
# Reads targets.txt (one base URL per line), writes a report. Changes nothing.
# The exact version markup differs by product/release - treat matches as a hint,
# then confirm on the host (step below).
$targets = Get-Content .\targets.txt
$results = foreach ($url in $targets) {
    try {
        $r = Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 10 -ErrorAction Stop
        # Broad match for version-like strings on the login page; tune to what
        # your deployment actually emits before trusting the output.
        $hits = [regex]::Matches($r.Content, '(?i)(version|build)[^0-9]{0,20}([0-9]+\.[0-9]+(\.[0-9]+)?)') |
                ForEach-Object { $_.Value } | Select-Object -Unique
        [pscustomobject]@{ Url = $url; VersionHints = ($hits -join '; '); Reachable = $true }
    } catch {
        [pscustomobject]@{ Url = $url; VersionHints = ''; Reachable = $false }
    }
}
$results | Format-Table -AutoSize
$results | Export-Csv .\atlassian-inventory.csv -NoTypeInformation

Same idea from a Linux jump box if that’s where you live:

run.shbash — zsh
#!/usr/bin/env bash
# Report-only. Prints URL plus any version-like strings from the login page.
# Confirm matches against the installed version on the host - the login-page
# markup is not a contract and changes between releases.
while read -r url; do
  html=$(curl -sk --max-time 10 "$url" || true)
  hints=$(grep -oiE '(version|build)[^0-9]{0,20}[0-9]+\.[0-9]+(\.[0-9]+)?' <<<"$html" \
            | sort -u | paste -sd'; ' -)
  printf '%s\t%s\n' "$url" "${hints:-unknown}"
done < targets.txt

Cross-check against reality on the hosts themselves, because the HTTP fingerprint only sees what’s exposed and lies as often as not. If you run config management, query the installed package or the version file in the install directory — that’s the authoritative number. If you don’t run config management across your Atlassian estate — well, that’s the other finding from this exercise.

2. Decide what’s internet-facing, because that’s your whole risk calculus

A pre-auth bug is a severity multiplier applied to your network exposure. Reachable from the internet: this is an incident waiting for a timestamp. Reachable only from an internal VLAN behind VPN: still serious — most breaches walk in through a phished laptop on that same VLAN — but you have hours, not minutes.

Don’t trust your mental model of the perimeter. Check it. Pull the external attack surface from whatever you’ve got — Shodan/Censys for the honest external view, or your own egress/ingress firewall rules — and reconcile it against the inventory from step 1. The instance you swear is internal is one misconfigured load balancer away from being the lead paragraph.

3. Get the affected ranges and fixed versions from Atlassian — not from me, not from a news aggregator

This is the step people skip and regret. When Atlassian publishes its advisory for CVE-2026-21589, read the affected-version table for each product you run, and note the exact fixed build. watchTowr’s write-up explains the mechanism; Atlassian’s advisory, once available, is the authoritative source for which versions are vulnerable and which build closes it. Jira and Confluence version independently, and different deployment lines may have different fixed builds. Match product-by-product against your step-1 CSV. “We patched Confluence” is not the same sentence as “we patched Jira.” Until that advisory exists, treat every instance you can’t confirm as potentially in-range and lean on the network controls below.

4. Patch. If you genuinely can’t patch today, buy time with the network

Patching is the fix. Everything below this line is a tourniquet, not surgery. Apply the fixed version Atlassian lists, on the internet-facing boxes first, then work inward.

When a change window fights you — and on a clustered node mid-sprint, it will — restrict who can reach the thing while you wait. Drop it behind VPN. Put an IP allowlist in front so only your office ranges and VPN pool can hit it. If there’s a WAF or reverse proxy in the path, block path-traversal patterns, though treat that as speed-bump, not wall: file-read bugs get re-encoded around signatures constantly, and a WAF rule you wrote against a PoC you half-understand is false confidence. The real control here is “fewer people can send the box a request,” not “we cleverly matched the exploit string.”

run.shbash — zsh
# Compensating control example: nginx allowlist in front of Confluence/Jira.
# Review each CIDR before applying. This denies by default.
location / {
    allow 203.0.113.0/24;   # office egress
    allow 198.51.100.0/24;  # VPN pool
    deny  all;
    proxy_pass http://atlassian_upstream;
}

5. Assume the secrets were already read — and plan to rotate

Here’s the part that separates a clean recovery from a six-month tail. With arbitrary file read, the attacker’s prize isn’t the application. It’s the files the application trusts. On a self-hosted Atlassian box, the juicy ones are predictable in category even if I’m not going to recite paths:

  • Database connection files — connection strings, often with plaintext or trivially reversible passwords.
  • Application configuration files holding keystore passwords and JVM arguments with secrets baked in.
  • Directory and SSO configuration — LDAP bind credentials, SAML/SSO signing details.
  • App-link and integration secrets, API tokens, and any properties file someone pasted a credential into “temporarily.”

If the instance was internet-facing and unpatched for any meaningful window, treat those credentials as disclosed. Rotate the database password, the directory bind account, the keystore, and every integration token — after patching, or you’ll just hand the new secrets through the same open window. Yes, rotating a Jira DB password is a pain. It’s a smaller pain than explaining why the attacker still had valid creds a month after you “remediated.”

6. Hunt your logs before you decide you got lucky

You can’t prove exploitation from the patch alone. Go to the access logs — Tomcat’s access log, your reverse proxy, your load balancer, wherever your deployment actually writes them — and look for the signatures of someone fishing for files: traversal sequences, encoded dots, unusual requests to endpoints that shouldn’t be serving file contents, and successful responses with suspicious sizes to unauthenticated requests.

run.shbash — zsh
# Report-only: surface candidate file-read / traversal attempts in access logs.
# Point LOGS at wherever your deployment writes access logs - e.g.
# /var/log/atlassian/*/access_log*, your nginx/apache logs, or the LB logs.
# Tune the endpoint pattern once the advisory names the vulnerable endpoint.
LOGS="/path/to/your/access_logs*"
grep -Ei '(\.\./|%2e%2e|%252e|/etc/passwd|\.cfg\.xml|dbconfig|server\.xml)' $LOGS \
  | awk '{print $1, $4, $6, $7, $9}' \
  | sort | uniq -c | sort -rn | head -n 50

Absence of hits in logs you only keep for seven days is not absence of compromise — it’s absence of evidence. Note that gap honestly in your write-up rather than rounding it up to “no impact.”

7. Fix the architecture that made this a crisis instead of a chore

The reason this bug is scary is that so many Atlassian instances sit directly on the internet, serving an admin-heavy app full of corporate secrets, because that was the easy way to let remote staff in five years ago. VPN-only or ZTNA-fronted access to Jira and Confluence turns the next pre-auth bug — and there will be a next one — from a fire drill into a Tuesday patch. Put the admin and setup endpoints behind an extra allowlist on top of that. This is the item that actually pays down risk; the rest of the list is you cleaning up because it wasn’t done.

Urgency, plainly: if it’s internet-facing, this is immediate — patch or firewall it off today, then rotate. If it’s internal-only behind VPN, it’s a this-week job you don’t get to defer into next cycle, because pre-auth file-read bugs are cheap to weaponize and these particular secrets are worth the effort.

If you do only one thing before you close the laptop tonight: confirm which of your Atlassian boxes answer from the internet, and take those off the internet. Patching can wait an hour. An open door can’t.