CVE-2026-55438
Executive Summary
CVE-2026-55438 is a same-origin policy bypass vulnerability in Coder, a platform for provisioning remote development environments via Terraform. The flaw resides in the subdomain-based workspace app proxy, where a crafted URL can bypass the same-owner CORS check. An attacker can exploit this by using a workspace-name subdomain segment that parses as a UUID, causing the workspace to be resolved by ID without verifying the URL's username matches the real owner. The CORS middleware then trusts the unverified username in the hostname, leading to potential cross-origin data access. Practical exploitation requires subdomain app routing (wildcard hostname) enabled and a victim who visits the attacker's crafted app URL while authenticated. The CVSS score is 5.8 (Medium), with low attack complexity and no privileges required, but user interaction is needed.
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
Coder is a Go-based application. The vulnerability is in the application's own code, not in a third-party package. However, organizations using Coder should verify their deployment version and apply patches promptly to prevent supply chain risks from compromised development environments.
CVSS Breakdown & Threat Level
- CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:L/A:N
- Base Score: 5.8 (Medium)
- Attack Vector: Network (AV:N)
- Attack Complexity: Low (AC:L)
- Privileges Required: None (PR:N)
- User Interaction: Required (UI:R)
- Scope: Unchanged (S:U)
- Confidentiality Impact: Low (C:L)
- Integrity Impact: Low (I:L)
- Availability Impact: None (A:N)
The threat level is medium due to the need for user interaction and the limited impact on confidentiality and integrity. However, in a development environment, this could lead to exposure of sensitive workspace data or code.
Deep Dive & Mechanics
The vulnerability is in Coder's subdomain-based workspace app proxy. When a user accesses a workspace via a subdomain like workspace-name.coder.example.com, the proxy resolves the workspace. The flaw occurs when the workspace-name subdomain segment is a UUID. In that case, the workspace is resolved by ID without checking that the username in the URL matches the actual owner of the workspace. The CORS middleware then trusts the unverified username, allowing a cross-origin request to be treated as same-origin.
Attack Flow:
- Attacker crafts a URL like
attacker-workspace-uuid.coder.example.com/app/some-endpoint. - The victim, authenticated to Coder, visits this URL.
- The proxy resolves the workspace by UUID, ignoring the username in the subdomain.
- The CORS middleware sees the username in the subdomain (e.g.,
attacker) and treats the request as same-origin. - The victim's browser sends authenticated requests to the attacker's workspace, potentially leaking data.
Root Cause: Insufficient validation of the subdomain username against the resolved workspace's owner.
Vulnerable vs. Patched Code
Vulnerable Code (Conceptual):
func resolveWorkspace(host string) (*Workspace, error) {
parts := strings.Split(host, ".")
username := parts[0]
workspaceName := parts[1]
// If workspaceName is a UUID, resolve by ID without checking username
if isUUID(workspaceName) {
return db.GetWorkspaceByID(workspaceName)
}
// Otherwise, resolve by username and workspace name
return db.GetWorkspaceByUserAndName(username, workspaceName)
}
Patched Code (Conceptual):
func resolveWorkspace(host string) (*Workspace, error) {
parts := strings.Split(host, ".")
username := parts[0]
workspaceName := parts[1]
// Always resolve by username and workspace name, even if UUID
workspace, err := db.GetWorkspaceByUserAndName(username, workspaceName)
if err != nil {
// Fallback to ID resolution but then verify owner
workspace, err = db.GetWorkspaceByID(workspaceName)
if err != nil {
return nil, err
}
if workspace.Owner != username {
return nil, errors.New("owner mismatch")
}
}
return workspace, nil
}
The patch ensures that even when resolving by UUID, the owner is verified against the username in the subdomain.
Exploitation & Lab Setup
Red Team
Prerequisites:
- Coder instance with subdomain app routing enabled (wildcard hostname).
- A victim user authenticated to Coder.
- An attacker workspace with a UUID name.
Exploitation Steps:
- Create a workspace with a UUID as its name (e.g.,
550e8400-e29b-41d4-a716-446655440000). - Craft a URL:
https://victim-username.550e8400-e29b-41d4-a716-446655440000.coder.example.com/app/some-endpoint. - Send this URL to the victim (e.g., via phishing email).
- When the victim visits, their browser sends authenticated requests to the attacker's workspace, potentially leaking data.
Proof of Concept (Python):
import requests
# Victim's session cookie
cookies = {"coder_session": "victim_session_token"}
# Attacker's workspace UUID
workspace_uuid = "550e8400-e29b-41d4-a716-446655440000"
# Victim's username
victim_username = "victim"
# Coder domain
domain = "coder.example.com"
url = f"https://{victim_username}.{workspace_uuid}.{domain}/app/some-endpoint"
response = requests.get(url, cookies=cookies)
print(response.text)
Blue Team
Detection:
- Monitor for unusual subdomain patterns where the workspace name is a UUID.
- Alert on CORS errors or unexpected cross-origin requests.
- Review logs for workspace resolution by ID without owner verification.
Hunting:
- Search for log entries where
workspace_nameis a UUID andusernamedoes not match the workspace owner. - Use the following Splunk query:
index=coder sourcetype=access_log
| rex field=uri "(?<username>[^.]+)\.(?<workspace_name>[^.]+)\.coder\.example\.com"
| where workspace_name MATCHES "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
| eval owner_check = if(username == workspace_owner, "match", "mismatch")
| where owner_check="mismatch"
Indicators of Compromise (IOCs)
- Network: HTTP requests to subdomains with UUID workspace names and mismatched usernames.
- Logs: Workspace resolution by ID without owner verification.
- File: No specific file IOCs.
- Registry: No registry IOCs.
Detection Engineering
YARA Rule
rule CVE_2026_55438_Coder_Bypass {
meta:
description = "Detects Coder subdomain CORS bypass attempts"
author = "Valters IT"
date = "2026-01-01"
reference = "CVE-2026-55438"
strings:
$uuid = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/
$subdomain = /[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]+\.coder\.example\.com/
condition:
$uuid and $subdomain
}
Sigma Rule
title: Coder Subdomain CORS Bypass Attempt
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects attempts to exploit CVE-2026-55438 by using UUID workspace names in subdomains
author: Valters IT
logsource:
category: webserver
product: coder
detection:
selection:
uri|contains: ".coder.example.com/"
uri|re: "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
condition: selection
falsepositives:
- Legitimate use of UUID workspace names
level: medium
Suricata Rule
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"CVE-2026-55438 Coder Subdomain CORS Bypass Attempt";
flow:to_server,established;
content:"Host"; http_header;
pcre:"/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.coder\.example\.com/Hi";
sid:1000001;
rev:1;
)
Remediation & Mitigation
Immediate:
- Upgrade Coder to versions 2.29.17, 2.32.7, 2.33.8, or 2.34.2.
- If upgrade is not possible, disable subdomain app routing (wildcard hostname) as a workaround.
Long-term:
- Implement additional validation of subdomain usernames against workspace owners.
- Monitor for similar bypass patterns in other parts of the application.
- Conduct regular security audits of CORS and authentication logic.
Valters IT Signature: This report was generated by Valters IT DevSecOps AI Assistant. For questions, contact security@valters-it.com.