Aug 19, 2026·7 min read·18 visits
Unauthenticated remote directory traversal in @logto/tunnel < 0.3.9 allows arbitrary file read via crafted GET requests when custom experience hosting is enabled.
A high-severity path traversal vulnerability exists in the @logto/tunnel npm package (part of the Logto repository) prior to version 0.3.9. Remote unauthenticated attackers can exploit this vulnerability to read arbitrary local files by sending crafted HTTP requests with directory traversal sequences when the static file proxy is active.
Logto serves as an open-source identity and access management system designed for modern multi-tenant environments. To facilitate custom sign-in flows, Logto contains a tunnel utility (@logto/tunnel) that allows developers to run a local static asset server for testing personalized web assets. When initialized, this tunnel exposes an interface through which clients can request custom HTML pages, stylesheets, and JavaScript files directly from a designated local workspace.
The exposure is located inside the static file proxy implementation within the @logto/tunnel package. When processing static asset requests, the tunnel service accepts the request path from the incoming HTTP transaction. Because this proxy function failed to isolate requests within the specified root directory, it opened an unauthenticated attack surface.
An attacker who can reach this proxy port can supply directory traversal sequences in the requested path. This enables the retrieval of sensitive filesystem objects. The vulnerability is cataloged as CVE-2026-63188 and carries a High severity CVSS v4.0 base score of 8.7.
The root cause of CVE-2026-63188 lies in the programmatic construction of filesystems paths using raw, unvalidated HTTP request paths. In vulnerable versions of @logto/tunnel prior to 0.3.9, the local server implemented static asset serving by resolving paths directly via Node.js native path modules. Specifically, the request route logic used request.url to match files within the directory provided by the --experience-path argument.
When an HTTP client executes a request, the request.url property contains the path portion of the request URL. In a secure static server implementation, this input must be treated as untrusted and normalized, percent-decoded, and validated to ensure it cannot escape the static root. However, the vulnerable logic directly supplied request.url to path.join.
The path.join utility in Node.js joins all given path segments together and normalizes the resulting path. If the joint path contains relative directory traversal characters such as ../, the utility evaluates these segments lexically. If the input contains a series of traversal segments that exceed the depth of the static root directory, the resolved path ascends beyond the root and references parent directories on the host operating system.
Once the lexical normalization completes, the application utilizes the resulting path string directly in an asynchronous filesystem opening function. Because the application executes no logical validation checking whether the resolved canonical target resides within the boundaries of the defined static directory, the operating system kernel fulfills the request. This exposes any file readable by the process owner.
To understand the mechanics of the patch, it is necessary to examine the vulnerable code path inside packages/tunnel/src/commands/tunnel/utils.ts. The vulnerable version processed requests through an unconstrained resolution sequence:
// VULNERABLE CODE PATH
if (request.method === 'HEAD' || request.method === 'GET') {
const fallBackToIndex = !isFileAssetPath(request.url);
// Vulnerability: No sanitization of request.url before joining with staticPath
const requestPath = path.join(staticPath, fallBackToIndex ? index : request.url);
const { range = '' } = request.headers;
const readFile = async (requestPath: string, start?: number, end?: number) => {
// Arbitrary file resolution and read
const fileHandle = await fs.open(requestPath, 'r');
// ... read and return file data
};
}The security remediation introduces the getSafeStaticFilePath helper in commit 5686815955534f803d3d50738259efd0f741e62c to enforce strict logical boundaries. Below is the updated, secure implementation:
// PATCHED CODE PATH
export const getSafeStaticFilePath = (staticPath: string, requestUrl: string) => {
// Step 1: Isolate the pathname from query and fragment identifiers
const [pathname = ''] = requestUrl.split(/[#?]/);
// Step 2: Safely percent-decode the pathname to handle obfuscated payloads
const decodedPathname = trySafe(() => decodeURIComponent(pathname));
// Step 3: Block Windows backslash sequences to prevent bypasses on Windows nodes
if (!decodedPathname || decodedPathname.includes('\\')) {
return;
}
// Step 4: Resolve the configured static path into an absolute canonical path
const staticRoot = path.resolve(staticPath);
// Step 5: Clean leading slashes from the request path to ensure relative mapping
const requestPath = decodedPathname.replace(/^\/+/, '');
// Step 6: Generate the final target resolution
const resolvedPath = path.resolve(staticRoot, requestPath);
// Step 7: Evaluate the relative position of the resolved file versus the root
const relativePath = path.relative(staticRoot, resolvedPath);
// Step 8: Strict guard - verify if target resolves outside the static boundaries
if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
return;
}
return resolvedPath;
};The introduced fix is robust. By processing path.relative(staticRoot, resolvedPath), the application explicitly measures the logical distance between the authorized root and the resolved target. If the output of path.relative begins with .., it mathematically proves that the targeted resource requires traveling upward from the static root. The inclusion of decodeURIComponent ensures that URL-encoded bypasses such as %2e%2e are decoded prior to calculation, preventing path traversal evasion.
Exploitation of CVE-2026-63188 is direct and does not require complex orchestration or prior authentication. An attacker must first establish network connectivity to the port exposed by the @logto/tunnel instance. Typically, this service is spawned when developers test localized customization flows, but if bound to wildcards (0.0.0.0), the port becomes accessible on local area networks or public addresses.
Once connectivity is confirmed, the attacker constructs HTTP GET requests containing directory traversal sequences. When using common utilities like curl, standard client-side path normalization will automatically resolve traversal sequences before transmission. Therefore, the attacker must supply the --path-as-is command-line flag or execute the request via raw socket streams.
# Standard exploitation targeting POSIX system files
curl --path-as-is http://target-host:3000/../../../../../../etc/passwd# Evasion attempt targeting Node.js execution on a Windows host
curl --path-as-is http://target-host:3000/..\\..\\..\\..\\Windows\\win.ini# Targeted extraction of local application dependencies and configuration structures
curl --path-as-is http://target-host:3000/../package.jsonUpon receiving these payloads, the server processes the traversal input. Since the server lacks validating checks, it attempts to open the corresponding OS path. The server then responds with an HTTP status code 200 and the content of the targeted system file in the response body.
The impact of this path traversal vulnerability is significant. While @logto/tunnel is primarily positioned as a development utility, developers often execute these services within cloud containers, staging instances, or local production systems. If the service is running with high OS-level privileges (such as root or Administrator), the entire filesystem becomes accessible to unauthenticated remote attackers.
Through arbitrary file read capabilities, attackers can exfiltrate sensitive files, including system secrets, configuration maps, environment variables containing API keys, database credentials, and SSH private keys. In modern microservice and cloud architectures, the leak of a single configuration file or environment block can allow an attacker to pivot and compromise entire cloud networks.
Additionally, reading application source code or operational metadata permits attackers to map out vulnerabilities inside surrounding software components. Since no write access is granted directly via this directory traversal, the impact is confined to high confidentiality loss (VC:H), while integrity (VI:N) and availability (VA:N) remain unaffected.
The primary and recommended mitigation for CVE-2026-63188 is upgrading @logto/tunnel to version 0.3.9 or higher. This upgrade ensures that the getSafeStaticFilePath helper actively validates and rejects traversal patterns before files are accessed. If immediate updates are not feasible, several defensive controls can be implemented to minimize risk.
First, modify the launch parameters of the tunnel utility to bind specifically to the loopback interface (127.0.0.1 or ::1) instead of the wildcard address. This limits exploitation capabilities to local processes on the host. Network access control lists or host-based firewall configurations must be configured to drop any inbound external packets directed at the tunnel ports.
For network detection, network intrusion detection systems (NIDS) can monitor traffic for suspicious traversal requests. Security engineers can also deploy Web Application Firewalls (WAF) to inspect incoming request paths and block requests containing relative path segments. Finally, running host-based file monitoring tools can help identify unauthorized reads to critical directories such as /etc or directory structural locations outside of web workspaces.
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
@logto/tunnel logto-io | < 0.3.9 | 0.3.9 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-22 |
| Attack Vector | Network (AV:N) |
| CVSS Score | 8.7 (High) |
| Exploit Status | Proof-of-Concept |
| KEV Status | Not Listed |
| Impact | Unauthenticated Arbitrary File Read (Confidentiality: High) |
Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
An LDAP injection vulnerability exists in the centraldogma-server-auth-shiro module of LY Corporation Central Dogma before version 0.84.0. The search logic dynamically constructs LDAP search filters by interpolating user-provided usernames without escaping RFC 4515 metacharacters. Unauthenticated remote attackers can leverage this flaw to bypass authentication, enumerate directory hierarchies, and access unauthorized resources.
CVE-2026-11746 is a critical vulnerability in Central Dogma Server prior to version 0.84.0, where an embedded ZooKeeper replication secret silently falls back to a publicly known, hard-coded default string ('ch4n63m3'). Remote attackers with access to the replication network can authenticate as legitimate cluster peers, potentially leading to unauthorized data exposure, state manipulation, or complete cluster takeover.
A logical verification flaw in ZITADEL's external JWT Identity Provider validation allows attackers to bypass session expiration checks. If an incoming JWT lacks the 'exp' claim, the system skips validation entirely, creating an indefinitely valid session. This issue has been addressed in versions 3.4.12 and 4.15.2.
CVE-2026-59149 identifies a directory traversal vulnerability in `@mockoon/commons-server`, the backend mock-server library powering the Mockoon application. The flaw occurs in the path containment validation logic used during raw file response generation. An unauthenticated attacker can exploit this weakness to retrieve arbitrary files from sibling directories sharing a common prefix with the designated static base directory.
An in-depth analysis of CVE-2026-59148, a high-severity flaw in Mockoon where unauthenticated administrative endpoints and a wildcard Cross-Origin Resource Sharing (CORS) policy allow remote execution, state poisoning, and credential theft.
An improper authentication vulnerability (CWE-287) in ZITADEL's external identity provider handler before version 4.15.3 allows remote attackers to perform complete account takeover. When auto-linking by email is enabled, ZITADEL verifies that the local target account has a verified email address but fails to verify if the external provider confirmed ownership of that same email. Attackers can exploit this by registering an unverified account with a victim's email address on a permissive external provider, leading to unauthorized account binding and persistent access.