CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Dashboard
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-27734
6.5

Docker API Path Traversal in Beszel Agent via Unsanitized Input

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 27, 2026·5 min read·3 visits

PoC Available

Executive Summary (TL;DR)

Beszel agents prior to v0.18.4 fail to sanitize container IDs before passing them to the Docker socket. Authenticated users can use '../' sequences to traverse the Docker API and access unauthorized system information.

A path traversal vulnerability exists in the Beszel server monitoring agent, allowing authenticated users to access arbitrary Docker Engine API endpoints. The vulnerability arises from improper sanitization of the 'container' query parameter when constructing requests to the Docker Unix socket. By injecting directory traversal sequences, an attacker with minimum privileges (including Read-Only) can escape the intended container scope and query sensitive host-level information, such as the Docker version, system info, or details of other containers running on the host.

Vulnerability Overview

Beszel is a lightweight server monitoring platform consisting of a central Hub and agents deployed on monitored systems. The agent gathers metrics, including Docker container statistics, by communicating with the local Docker engine via a Unix Domain Socket (UDS). To provide container-specific logs and information, the Hub proxies requests to the agent, which then queries the Docker API.

In versions prior to 0.18.4, the Beszel Agent contains a Path Traversal vulnerability (CWE-22). The agent accepts a container identifier from the Hub without sufficient validation. This identifier is used to construct the URL path for requests sent to the Docker daemon. Because the agent does not sanitize this input or strictly enforce an allowlist of valid container ID formats, an attacker can supply directory traversal sequences (../).

This flaw allows an authenticated user to break out of the intended API path (typically /containers/<id>/...) and access the root of the Docker Engine API. Consequently, an attacker can retrieve sensitive information about the host's Docker configuration and other running workloads, bypassing the intended restrictions of the Beszel interface.

Root Cause Analysis

The vulnerability is caused by the insecure concatenation of user-supplied input into a path used for a Unix socket connection, combined with specific behaviors of the Go HTTP client.

1. Unsafe String Interpolation: The Beszel agent constructs the request URL for the Docker socket using fmt.Sprintf. The code takes the container string directly from the incoming request query parameters and injects it into a format string like /containers/%s/json. No prior validation checks if the input is a valid hexadecimal container ID or if it contains control characters.

2. Unix Socket Path Behavior: When communicating over HTTP/TCP, many libraries and proxies automatically normalize paths, resolving ../ sequences before the request leaves the client. However, when using Go's http.Client to communicate over a Unix Domain Socket (via the http+unix scheme or similar custom transport), path normalization is often less aggressive or non-existent for the path component sent to the socket. The raw path containing ../ is transmitted to the Docker daemon.

3. Docker Daemon Resolution: The Docker daemon receives the request path (e.g., /containers/../../version). The internal router of the Docker engine resolves the traversal, treating the request as a query for /version. This effectively bypasses the application logic that intended to restrict the user to specific container operations.

Code Analysis

The following analysis highlights the vulnerable logic and the remediation applied in version 0.18.4. The fix introduces strict input validation and proper URL encoding.

Vulnerable Implementation

In the vulnerable version, the agent accepted the container parameter and used it directly. The lack of url.PathEscape allowed special characters to pass through to the socket request.

// Vulnerable Code Pattern (Conceptual)
func getContainerLogs(w http.ResponseWriter, r *http.Request) {
    containerID := r.URL.Query().Get("container")
    // FLAW: Direct interpolation of user input into the path
    targetPath := fmt.Sprintf("/containers/%s/logs", containerID)
    
    // The client sends this path raw to the Unix socket
    resp, err := dockerClient.Get("http://unix" + targetPath)
    // ...
}

Patched Implementation (Commit 311095c)

The patch introduces two layers of defense: regex validation to ensure the ID is a hex string, and URL escaping as a fallback safety measure.

// Fixed Code Pattern
import (
    "net/url"
    "regexp"
)
 
// 1. Strict Validation: Enforce 12-64 char hex string
var containerIDPattern = regexp.MustCompile(`^[a-fA-F0-9]{12,64}$`)
 
func getContainerLogs(w http.ResponseWriter, r *http.Request) {
    containerID := r.URL.Query().Get("container")
 
    // 2. Reject invalid formats immediately
    if !containerIDPattern.MatchString(containerID) {
        http.Error(w, "Invalid container ID", http.StatusBadRequest)
        return
    }
 
    // 3. Encode the path component (Defense in Depth)
    // Even if the regex failed, this would convert "../" to "%2E%2E%2F"
    targetPath := fmt.Sprintf("/containers/%s/logs", url.PathEscape(containerID))
    
    resp, err := dockerClient.Get("http://unix" + targetPath)
    // ...
}

Exploitation Methodology

An attacker can exploit this vulnerability to enumerate the host system's Docker environment. Access to the Beszel Hub is required, but the account can have minimal privileges (e.g., a read-only user).

Prerequisites:

  • Network access to the Beszel Hub.
  • Valid credentials (JWT) for a user account.
  • The system ID of a target agent (visible in the URL when viewing a system in the dashboard).

Attack Steps:

  1. Authenticate: The attacker logs into the Beszel Hub and obtains a Bearer token.
  2. Target Selection: The attacker navigates to the dashboard to find the internal ID of a monitored system (e.g., 1).
  3. Payload Construction: The attacker crafts a GET request to the proxy endpoint. Instead of a valid container ID, they inject a traversal payload targeting the Docker Engine version endpoint.

Proof of Concept:

GET /api/beszel/containers/info?system=1&container=../../version HTTP/1.1
Host: beszel.internal
Authorization: Bearer <JWT_TOKEN>

Result: The server responds with the JSON output from the Docker Engine's /version endpoint, disclosing the Go version, kernel version, and build details. By changing the payload to ../../info or ../../containers/json, the attacker can list all running containers or inspect swarm details.

Impact Assessment

The successful exploitation of CVE-2026-27734 results in unauthorized Information Disclosure. While the attack is authenticated, the ability for a low-privilege user to access the underlying infrastructure API represents a significant privilege escalation within the context of the application.

  • Confidentiality (High): Attackers can query endpoints like /info, /version, /images/json, and /containers/json. This exposes the internal architecture, list of running services, image names, and potential environment variables if /containers/<id>/json is targeted for arbitrary containers.
  • Integrity (None): The vulnerability affects GET requests (logs/info endpoints). There is no documented path to issue POST or DELETE commands via this specific vector, limiting the ability to modify state.
  • Availability (None): The vulnerability does not inherently allow for denial of service.

CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N (6.5 Medium). The scope is Unchanged (S:U) because the vulnerable component (Beszel Agent) and the impacted component (Docker Engine) are on the same local system boundary, although the data accessed belongs to the infrastructure layer.

Official Patches

BeszelCommit fixing path traversal via regex validation

Fix Analysis (1)

Technical Appendix

CVSS Score
6.5/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

Affected Systems

Beszel Agent < 0.18.4Beszel Hub < 0.18.4

Affected Versions Detail

Product
Affected Versions
Fixed Version
Beszel
HenryGD
< 0.18.40.18.4
AttributeDetail
CWE IDCWE-22
Attack VectorNetwork
CVSS6.5 (Medium)
ImpactInformation Disclosure
ProtocolHTTP over Unix Socket
Exploit StatusProof of Concept Available

MITRE ATT&CK Mapping

T1083File and Directory Discovery
Discovery
T1005Data from Local System
Collection
CWE-22
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')

The software uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the software does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.

Known Exploits & Detection

GitHub AdvisoryOfficial advisory containing reproduction steps

Vulnerability Timeline

Fix commit 311095c pushed
2026-02-18
Public Disclosure (GHSA)
2026-02-27
CVE-2026-27734 Published
2026-02-27

References & Sources

  • [1]GHSA-phwh-4f42-gwf3
  • [2]NVD - CVE-2026-27734

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.