Jul 17, 2026·8 min read·27 visits
Unauthenticated WebSocket connection upgrade allows remote attackers to impersonate EV charging stations, spoof transactions, and disrupt critical grid infrastructure.
A critical improper access control vulnerability (CWE-284) in the WebSocket upgrade endpoint of Le Circuit Électrique charging station backend allows remote, unauthenticated attackers to connect to the Charging Station Management System and impersonate charging stations.
CVE-2026-20744 defines a critical improper access control vulnerability within the backend infrastructure of Le Circuit Électrique, an electric vehicle charging station network operated by Hydro-Québec. The vulnerability resides specifically within the WebSocket endpoint exposed by the Charging Station Management System (CSMS) backend. This endpoint is responsible for processing incoming connections from physical charging stations using the Open Charge Point Protocol (OCPP).
Because the endpoint lacks authentication controls during the connection establishment phase, external actors can establish unauthorized communication channels with the CSMS. The affected backend exposes a public-facing network interface that handles these persistent, bidirectional WebSocket connections. Under normal operating conditions, this interface manages transactional, diagnostic, and state data between physical charging stations and the central management system.
The vulnerability is classified under CWE-284 (Improper Access Control). If exploited, the flaw permits an unauthenticated remote attacker to connect directly to the backend server and impersonate any legitimate charging station. This unauthorized connection serves as a vector for privilege escalation and subsequent exploitation of downstream charging services.
The root cause of CVE-2026-20744 lies in the failure of the WebSocket upgrade handler to validate the client's identity before upgrading the HTTP connection to a WebSocket session. The backend system implements the Open Charge Point Protocol (OCPP) over WebSockets (typically OCPP 1.6J or OCPP 2.0.1) for bidirectional telemetry and control. This architecture relies on persistent TCP connections initiated by the charging stations to bypass typical network address translation (NAT) barriers.
In a secure implementation, the CSMS backend must perform strict authentication during the initial HTTP GET request containing the Upgrade: websocket header. This authentication is standardly performed using either Mutual TLS (mTLS) with client certificates or HTTP basic authentication tokens transmitted in the request headers. The vulnerable routing mechanism in Le Circuit Électrique backend omitted these verification steps, processing the upgrade request based solely on the path variable.
The backend router matched incoming upgrade requests to a dynamic route structure containing the unique identifier of the charging station, such as /ocpp/{ChargePointId}. The router accepted the connection and upgraded the protocol without verifying if the requesting client possessed the cryptographic keys or credentials associated with that specific ChargePointId. Once the protocol upgrade completed, the backend registered the physical connection as a trusted node within its state machine, associating the TCP socket directly with the identifier provided in the URL.
An analysis of the architectural flaw indicates that the connection upgrade logic failed to intercept and authorize the HTTP upgrade request before establishing the WebSocket channel. The following pseudocode models the vulnerable routing and handshake handling mechanism.
// VULNERABLE: The handler upgrades connections based purely on the path parameter without authentication
func (h *OcppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Extract the charging station identifier directly from the URL path
vars := mux.Vars(r)
chargePointID := vars["ChargePointId"]
// Missing authentication check: Anyone can specify any ChargePointId in the URL path
// No mTLS validation is performed on r.TLS.PeerCertificates
// No token validation is performed on r.Header.Get("Authorization")
// Upgrade the connection to a persistent WebSocket session
conn, err := h.upgrader.Upgrade(w, r, nil)
if err != nil {
log.Printf("Failed to upgrade connection for station %s: %v", chargePointID, err)
return
}
// The backend registers the active connection under the unauthenticated ID
h.registry.Register(chargePointID, conn)
}The remediation requires intercepting the HTTP request prior to executing the connection upgrade. Secure implementations must enforce either client certificate verification or token validation. The following example demonstrates the remediated logic incorporating basic authentication token verification and client certificate mapping:
// PATCHED: The handler validates authorization headers and client certificates before protocol upgrade
func (h *OcppHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
chargePointID := vars["ChargePointId"]
// 1. Enforce TLS Client Certificate validation if configured
if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
clientCert := r.TLS.PeerCertificates[0]
if err := h.validator.VerifyCertificate(clientCert, chargePointID); err != nil {
http.Error(w, "Unauthorized: Invalid client certificate mapping", http.StatusUnauthorized)
return
}
} else {
// Fall back to token-based authorization if mTLS is not active on this interface
authToken := r.Header.Get("Authorization")
if authToken == "" || !h.validator.VerifyToken(chargePointID, authToken) {
http.Error(w, "Unauthorized: Missing or invalid security token", http.StatusUnauthorized)
return
}
}
// Protocol upgrade is only initiated after authentication succeeds
conn, err := h.upgrader.Upgrade(w, r, nil)
if err != nil {
log.Printf("Failed to upgrade authenticated connection: %v", err)
return
}
h.registry.Register(chargePointID, conn)
}By ensuring that the WebSocket upgrade handshake is conditionally approved, unauthorized clients are blocked at the HTTP layer, preventing the establishment of unauthenticated stateful connections.
Exploitation of CVE-2026-20744 relies on network access to the public-facing port of the CSMS backend. The attacker does not require valid administrative credentials, session cookies, or cryptographic certificates to initiate the attack. The process is deterministic and can be automated via standard scripting libraries that support WebSocket handshakes.
The initial phase of the attack requires identifying the target backend domain and discovering valid charging station identifiers. Station identifiers are frequently visible physically on the charging kiosks or can be inferred through sequential numbering schemes. Once a valid target identifier is obtained, the attacker constructs an HTTP upgrade request directed at the corresponding path.
GET /ocpp/STATION-ID-99881 HTTP/1.1
Host: csms.lecircuitelectrique.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13Upon receiving this request, the vulnerable backend returns a 101 Switching Protocols response, establishing the WebSocket connection. The attacker then transmits standard OCPP payload messages formatted as JSON over the established subprotocol channel. By executing a BootNotification or a StatusNotification message, the attacker changes the internal state representation of the target station inside the CSMS database.
This connection allows the attacker to hijack the operational context of the specified charging station. The attacker can spoof transactions, authorize unpaid charging sessions, modify user billing records, or inject malicious diagnostic reports. Additionally, since the backend associates the physical connection with the provided ChargePointId, the legitimate physical charging station may be disconnected or denied service due to duplicate connection conflicts.
The security impact of CVE-2026-20744 is evaluated as critical, receiving a CVSS v3.1 base score of 9.8. Because the vulnerability is exploitable remotely without privileges or user interaction, the threat vector presents a severe risk to critical infrastructure assets. The impact is categorized across three major operational axes: integrity, availability, and confidentiality.
Integrity risks are particularly high due to the nature of the OCPP protocol. Attackers who successfully impersonate charging stations can inject falsified transaction records, allowing fraudulent charging sessions to be billed to arbitrary user accounts. They can also falsify telemetry, reporting active charging loops as idle or error-states, which corrupts the analytical databases used for fleet management and load balancing.
Availability risks affect both individual charging stations and the broader grid distribution network. By establishing concurrent connections under existing station IDs, attackers can force legitimate stations offline. Furthermore, injecting coordinated commands across thousands of impersonated nodes can simulate sudden, massive spikes in power demand, potentially disrupting local grid stability. Confidentiality is compromised through exposure of user session tokens, transaction logs, and internal backend routing endpoints.
Remediation of CVE-2026-20744 requires implementing strict authentication validations at the edge of the CSMS network before connections reach the application layer. The primary fix deployed by Hydro-Québec involved disabling the OCPP interface across stations where backend synchronization was not actively required. This action significantly reduced the exposed attack surface.
For endpoints that require persistent OCPP communication, organizations must enforce Mutual TLS (mTLS) configuration. The reverse proxy, load balancer, or API gateway must reject any incoming connection that does not present a client certificate signed by a trusted internal Certificate Authority (CA). The backend code must also map the Common Name (CN) or Subject Alternative Name (SAN) of the client certificate directly to the requested ChargePointId in the URI path to prevent cross-station impersonation.
If mTLS cannot be deployed immediately due to legacy hardware constraints on physical charging kiosks, administrators must enforce HTTP Basic Authentication or bearer tokens inside the WebSocket handshake headers. The CSMS backend must perform a database lookup of these credentials before issuing the 101 Switching Protocols handshake response. Finally, network-level isolation via private Access Point Names (APNs) must be configured to ensure charging station telemetry is routed through encrypted, private cellular channels rather than the public internet.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Le Circuit Électrique charging station backend Hydro-Québec | < June 2026 | June 2026 Update |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-284 |
| Attack Vector | Network |
| CVSS Severity Score | 9.8 (Critical) |
| EPSS Score | 0.00519 (Percentile: 40.63%) |
| Primary Impact | Privilege Escalation and Charging Station Impersonation |
| Exploit Status | None (No public PoC or active exploitation) |
| CISA KEV Status | Not Listed |
The software does not restrict or incorrectly restricts access to a resource from an unauthorized actor.
A remote code execution vulnerability exists in Microsoft .NET due to untrusted data deserialization within the PresentationCore component. The flaw stems from implicit auto-conversion flags during clipboard data retrieval operations.
An out-of-bounds write vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio allows unauthenticated remote attackers to execute arbitrary code via crafted pixel-shader bytecode or auto-converted clipboard payloads.
ASP.NET Core contains a thread deadlock vulnerability (CWE-833) that allows an unauthenticated remote attacker to cause a denial of service over the network by exhausting server thread pool resources.
CVE-2026-70035 is a high-severity Remote Code Execution (RCE) vulnerability in Microsoft .NET Framework, .NET runtime, and Visual Studio caused by improper handling during the deserialization of untrusted data (CWE-502). An unauthenticated attacker can execute arbitrary code within the context of the affected process by delivering a crafted serialized payload.
An elevation of privilege vulnerability exists in ASP.NET Core and Microsoft Visual Studio due to improper synchronization during concurrent thread execution. Authenticated remote attackers with low privileges can exploit a timing window to manipulate shared resources and assume higher-level execution contexts.
A path traversal vulnerability (CWE-22) in Contao CMS allows unauthenticated remote attackers to bypass directory boundary restrictions in ImagesController and access files within the project directory.